#IMPORTANT NOTE: everything for plotting in figures currently comes from the second_timepoint object, but there are additional chunks that run similar analyses on all_data objects with different cluster numbers

#Set working directory to appropriate folder for inputs and outputs on Google Drive

#Initialize

Load data

rm(list = ls())
library(dplyr)
library(Seurat)
library(ggplot2)
library(RColorBrewer)
library(xlsx)

cluster second timepoint and plot

load('2022_01_14_analysis_scripts/2022_05_27_analysis/Preprocess_GEX/Objects_premerged.RData')
load('2022_01_14_analysis_scripts/2022_05_27_analysis/Preprocess_GEX/second_timepoint_merged.RData')
load('2022_01_14_analysis_scripts/2022_05_27_analysis/Preprocess_GEX/first_timepoint_merged.RData')

This is the same chunk as above but it makes the plots as bar charts in individual PDFs for pulling into illustrator

second_timepoint <- NormalizeData(second_timepoint)
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
second_timepoint <- FindVariableFeatures(second_timepoint, selection.method = 'vst', nFeatures = 20000)
Warning: The following arguments are not used: nFeatures
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
second_timepoint <- ScaleData(second_timepoint)
Centering and scaling data matrix

  |                                                                                                                                     
  |                                                                                                                               |   0%
  |                                                                                                                                     
  |================================================================                                                               |  50%
  |                                                                                                                                     
  |===============================================================================================================================| 100%
second_timepoint <- RunPCA(second_timepoint)
PC_ 1 
Positive:  IGFBP7, COL1A1, BASP1, TPM1, CAV1, ARL4C, FN1, RTN4, MMP2, TXNRD1 
       C12orf75, CALD1, SPOCK1, THBS1, MYL6, ANXA1, COL6A1, TPM4, CALM2, IL6ST 
       COL6A2, MYOF, PRNP, C1R, TMSB4X, DSTN, CRIM1, ANXA2, SFRP1, CEMIP 
Negative:  PMEL, MLANA, LHFPL3-AS1, FRMD4B, DCT, S100B, CAPN3, PRDX1, BCAS3, APOD 
       RAMP1, VGF, RGS1, IRS2, C11orf96, RLBP1, CITED1, BAAT, AKR1A1, LINC01531 
       FABP7, SCML4, CEACAM1, ATP6V0D2, CSTB, EDNRB, HSPA1A, CPM, TRIM63, TRPM1 
PC_ 2 
Positive:  MT2A, TMEM158, MMP1, STC1, CCND1, SCG2, IER3, PHLDA1, TFPI2, KYNU 
       VEGFA, SFRP1, LINC02376, WNT5A, SERPINB2, HPCAL1, AKR1B1, SIRPB1, GNG11, EREG 
       LTBP1, ITGA2, MYEOV, CD44, SLC16A6, MMP3, ANGPTL4, NRP1, TIMP3, MAP4K4 
Negative:  CRYAB, IFI6, S100B, AEBP1, SPARC, MFGE8, PMP22, SORBS2, C1orf198, LIMA1 
       PALLD, ANK3, CTSK, COL9A3, HSPG2, IFITM3, LIMCH1, GREM2, PLP1, SCRG1 
       GAS7, CEBPD, OLFML2A, ISG15, EPB41L3, AKAP12, IFI27, APOE, LMCD1, NUPR1 
PC_ 3 
Positive:  MALAT1, FTH1, FTL, NEAT1, MMP1, FN1, NDRG1, SCG2, IGFBP5, RND3 
       TIMP1, CEBPD, GAS5, ADM, DEPP1, RGS2, IGFBP7, LINC00968, INHBA, JUN 
       STC1, ARL4C, UBC, IL6ST, TMSB4X, TFPI2, NNMT, PTGS2, FGF7, IER3 
Negative:  MKI67, CENPF, TPX2, ASPM, UBE2S, NUSAP1, GTSE1, ANLN, TOP2A, H2AFZ 
       BIRC5, PRC1, HIST1H1B, UBE2C, HIST1H4C, TMPO, TUBA1B, CEP55, CENPE, HMGB2 
       CCNB1, HMMR, TK1, NCAPG, PRR11, PCLAF, AURKB, UBE2T, DBF4, CDKN3 
PC_ 4 
Positive:  OLFML2A, EPB41L3, HSPG2, COL9A3, NGFR, CRYAB, ITGA6, ITGA2, SCRG1, DLX5 
       SEMA3B, H19, TSPAN13, GAS7, NCAM1, TRIM58, NTRK2, SERPINE2, ANK3, NFATC2 
       TSC22D1, SLITRK6, MAP4K4, EVI5, PHACTR1, LRRTM4, AKAP12, GRIK2, HTRA1, MALAT1 
Negative:  BST2, IFI27, VCAM1, COL14A1, XAF1, APOE, SFRP4, LINC00968, C1R, LINC01914 
       GBP1, DEPP1, CTSK, CARD16, IFI44L, PDE5A, PLAAT4, GYPC, DCN, PSMB9 
       NUPR1, LBP, FOSB, TSLP, NNMT, CCL2, BGN, C1S, RPS27L, IFITM3 
PC_ 5 
Positive:  VCAM1, IGFBP5, BOC, COL14A1, FOXF1, KYNU, PLAAT4, CTSC, MMD, CARD16 
       TRPA1, C1R, LBP, PDGFRA, IRF1, PMEPA1, PCDH18, WNT5A, FENDRR, CASP1 
       DCN, CSRP2, LAMB1, SOST, AGT, TBX2, MGST1, SLC7A11, FOXF2, FAM20C 
Negative:  CPA4, KRT34, SERPINE1, SMYD3, LINC01638, AC092807.3, DKK1, C12orf75, TNIK, FGF5 
       OXTR, SRGN, SPOCK1, CDA, CCN5, GRAMD2B, ARL4C, EPGN, SPOCD1, SCG5 
       MME, CRISPLD2, TPST2, STON2, TNFRSF12A, CSTB, RPS27L, GCNT1, LMO7, RASD2 
second_timepoint <- FindNeighbors(second_timepoint, dims = 1:15)
Computing nearest neighbor graph
Computing SNN
second_timepoint <- FindClusters(second_timepoint, resolution = 0.5)
Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck

Number of nodes: 57996
Number of edges: 1751932

Running Louvain algorithm...
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.9022
Number of communities: 14
Elapsed time: 13 seconds
second_timepoint <- RunUMAP(second_timepoint, dims = 1:15)
09:22:25 UMAP embedding parameters a = 0.9922 b = 1.112
09:22:25 Read 57996 rows and found 15 numeric columns
09:22:25 Using Annoy for neighbor search, n_neighbors = 30
09:22:25 Building Annoy index with metric = cosine, n_trees = 50
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
09:22:30 Writing NN index file to temp file /var/folders/ph/24prrxys02179y9_qzhxjgvc0000gn/T//RtmpH55A7T/file13f1572bdbb96
09:22:31 Searching Annoy index using 1 thread, search_k = 3000
09:22:48 Annoy recall = 100%
09:22:48 Commencing smooth kNN distance calibration using 1 thread with target n_neighbors = 30
09:22:50 Initializing from normalized Laplacian + noise (using irlba)
09:22:52 Commencing optimization for 200 epochs, with 2501536 positive edges
Using method 'umap'
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
09:23:25 Optimization finished
cells_per_cluster <- data.frame (Cluster = as.numeric(second_timepoint$seurat_clusters), Condition = second_timepoint$OG_condition)
cells_per_cluster_list <- list()

pdf('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/original_condition_second_timepoint.pdf')
print(DimPlot(second_timepoint))
print(DimPlot(second_timepoint, label = T, group.by = 'OG_condition', cols = c('dabtramtodabtram' = '#561E59', 'dabtramtococl2' = '#A2248E', 'dabtramtocis' = '#9D85BE', 'cocl2todabtram' = '#10413B', 'cocl2tococl2' = '#6ABD45', 'cocl2tocis' = '#6DC49C', 'cistodabtram' = '#A23622', 'cistococl2' = '#F49129', 'cistocis' = '#FBD08C')))

for (i in 1:(max(cells_per_cluster$Cluster))){
  currentcluster <- filter(cells_per_cluster, cells_per_cluster$Cluster == i)
  cells_per_cluster_list[[paste0('Cluster', i)]] <- data.frame(table(currentcluster$Condition))
  
  print(ggplot(cells_per_cluster_list[[paste0('Cluster', i)]], aes(x ='', y = Freq, fill = Var1)) + geom_bar(stat = 'identity') + coord_polar('y', start = 0) + theme_void() + scale_fill_manual(values = c('dabtramtodabtram' = '#561E59', 'dabtramtococl2' = '#A2248E', 'dabtramtocis' = '#9D85BE', 'cocl2todabtram' = '#10413B', 'cocl2tococl2' = '#6ABD45', 'cocl2tocis' = '#6DC49C', 'cistodabtram' = '#A23622', 'cistococl2' = '#F49129', 'cistocis' = '#FBD08C')) + labs(title = paste('Original condition of cells in cluster', i-1)))
}
Warning: stack imbalance in 'lapply', 83 then 81
dev.off()
null device 
          1 

#editing cells_per_cluster so that the condition name is whatever second condition

#UMAPs highlighting all cells that had same first and second drug in second_timepoint object


cells_per_cluster_seconddrug <- cells_per_cluster
cells_per_cluster_firstdrug <- cells_per_cluster

for (i in 1:nrow(cells_per_cluster)){
  if (cells_per_cluster$Condition[[i]] == "dabtramtodabtram" || cells_per_cluster$Condition[[i]] == "cistodabtram" || cells_per_cluster$Condition[[i]] == "cocl2todabtram") {
    cells_per_cluster_seconddrug$Condition[[i]] <- "dabtramsecond"
  }
  if (cells_per_cluster$Condition[[i]] == "cocl2tococl2" || cells_per_cluster$Condition[[i]] == "cistococl2" || cells_per_cluster$Condition[[i]] == "dabtramtococl2") {
    cells_per_cluster_seconddrug$Condition[[i]] <- "cocl2second"
  }
  if (cells_per_cluster$Condition[[i]] == "cistocis" || cells_per_cluster$Condition[[i]] == "cocl2tocis" || cells_per_cluster$Condition[[i]] == "dabtramtocis") {
    cells_per_cluster_seconddrug$Condition[[i]] <- "cissecond"
  }
}

for (i in 1:nrow(cells_per_cluster)){
  if (cells_per_cluster$Condition[[i]] == "dabtramtodabtram" || cells_per_cluster$Condition[[i]] == "dabtramtocis" || cells_per_cluster$Condition[[i]] == "dabtramtococl2") {
    cells_per_cluster_firstdrug$Condition[[i]] <- "dabtramfirst"
  }
  if (cells_per_cluster$Condition[[i]] == "cocl2tococl2" || cells_per_cluster$Condition[[i]] == "cocl2tocis" || cells_per_cluster$Condition[[i]] == "cocl2todabtram") {
    cells_per_cluster_firstdrug$Condition[[i]] <- "cocl2first"
  }
  if (cells_per_cluster$Condition[[i]] == "cistocis" || cells_per_cluster$Condition[[i]] == "cistococl2" || cells_per_cluster$Condition[[i]] == "cistodabtram") {
    cells_per_cluster_firstdrug$Condition[[i]] <- "cisfirst"
  }
}

#now colored based on second drug only
for (i in 1:(max(cells_per_cluster_seconddrug$Cluster))){
  pdf(paste0('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/end_condition_second_timepoint', i-1, '.pdf'))
  currentcluster <- filter(cells_per_cluster_seconddrug, cells_per_cluster_seconddrug$Cluster == i)
  cells_per_cluster_list[[paste0('Cluster', i)]] <- data.frame(table(currentcluster$Condition))
  
  print(ggplot(cells_per_cluster_list[[paste0('Cluster', i)]], aes(x ='', y = Freq, fill = Var1)) + geom_bar(position = 'fill', stat = 'identity') + scale_fill_manual(values = c('dabtramsecond' = '#623594', 'cocl2second' = '#0F8241', 'cissecond' = '#C96D29')) + labs(title = paste('End condition of cells in second timepoint cluster', i-1)))
  dev.off()
}

#now colored based on first drug only
for (i in 1:(max(cells_per_cluster_firstdrug$Cluster))){
  pdf(paste0('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/first_condition_second_timepoint', i-1, '.pdf'))
  currentcluster <- filter(cells_per_cluster_firstdrug, cells_per_cluster_firstdrug$Cluster == i)
  cells_per_cluster_list[[paste0('Cluster', i)]] <- data.frame(table(currentcluster$Condition))
  
  print(ggplot(cells_per_cluster_list[[paste0('Cluster', i)]], aes(x ='', y = Freq, fill = Var1)) + geom_bar(position = 'fill', stat = 'identity') + scale_fill_manual(values = c('dabtramfirst' = '#623594', 'cocl2first' = '#0F8241', 'cisfirst' = '#C96D29')) + labs(title = paste('End condition of cells in first timepoint cluster', i-1)))
  dev.off()
}

#UMAPs highlighting all cells that had same first drug in first_timepoint object

cells_per_condition <- list()
for (i in c('dabtramtodabtram', 'dabtramtococl2', 'dabtramtocis', 'cocl2todabtram', 'cocl2tococl2', 'cocl2tocis', 'cistodabtram', 'cistococl2', 'cistocis')){
  cells_per_condition[[paste0(i, '_cells')]] <- names(second_timepoint$orig.ident[second_timepoint$OG_condition == i])
}

pdf('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/drug_group_highlights.pdf')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$dabtramtodabtram_cells, cells_per_condition$dabtramtocis_cells, cells_per_condition$dabtramtococl2_cells),
        cols.highlight = ('red')) + ggtitle('dabtram first cells')
DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cocl2tococl2_cells, cells_per_condition$cocl2tocis_cells, cells_per_condition$cocl2todabtram_cells),
        cols.highlight = ('red')) + ggtitle('cocl2 first cells')
DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cis_cells, cells_per_condition$cistocis_cells, cells_per_condition$cistococl2_cells, cells_per_condition$cistodabtram_cells),
        cols.highlight = ('red')) + ggtitle('cis first cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$dabtramtodabtram_cells, cells_per_condition$cistodabtram_cells, cells_per_condition$cocl2todabtram_cells),
        cols.highlight = ('blue')) + ggtitle('dabtram second cells')
DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cocl2tococl2_cells, cells_per_condition$cistococl2_cells, cells_per_condition$dabtramtococl2_cells),
        cols.highlight = ('blue')) + ggtitle('cocl2 second cells')
DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cis_cells, cells_per_condition$cistocis_cells, cells_per_condition$cocl2tocis_cells, cells_per_condition$dabtramtocis_cells),
        cols.highlight = ('blue')) + ggtitle('cis second cells')

dev.off()
null device 
          1 

#More plots not in PDF but just for quick visualizations

pdf('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/drug_group_highlights_first_timepoint.pdf')

DimPlot(first_timepoint, reduction = "umap", dims = c(1,2), group.by = "OG_condition", pt.size = 2, cols =  c('dabtram' = '#623594', 'cocl2' = '#0F8241', 'cis' = '#C96D29'))
DimPlot(first_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(names(first_timepoint$orig.ident[first_timepoint$OG_condition == 'dabtram'])),
        cols.highlight = ('red')) + ggtitle('dabtram first cells')
DimPlot(first_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(names(first_timepoint$orig.ident[first_timepoint$OG_condition == 'cocl2'])),
        cols.highlight = ('red')) + ggtitle('cocl2 first cells')
DimPlot(first_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(names(first_timepoint$orig.ident[first_timepoint$OG_condition == 'cis'])),
        cols.highlight = ('red')) + ggtitle('cis first cells')

FeaturePlot(first_timepoint, features = 'EGFR', pt.size = 2) +
  scale_colour_gradientn(colors = rev(brewer.pal(n = 11, name = 'RdBu')))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
FeaturePlot(first_timepoint, features = 'NGFR', pt.size = 2) +
  scale_colour_gradientn(colors = rev(brewer.pal(n = 11, name = 'RdBu')))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
dev.off()
null device 
          1 
DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cocl2tococl2_cells, cells_per_condition$cocl2tocis_cells, cells_per_condition$cocl2todabtram_cells),
        cols.highlight = c('#10413b', '#6dc49c', '#6abd45')) + ggtitle('cocl2 first cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cocl2tococl2_cells, cells_per_condition$cocl2tocis_cells, cells_per_condition$cocl2todabtram_cells),
        cols.highlight = ('#0f8241')) + ggtitle('cocl2 first cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cocl2tococl2_cells, cells_per_condition$cistococl2_cells, cells_per_condition$dabtramtococl2_cells),
        cols.highlight = c('#a2248e', '#f49129', '#6abd45')) + ggtitle('cocl2 second cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cocl2tococl2_cells, cells_per_condition$cistococl2_cells, cells_per_condition$dabtramtococl2_cells),
        cols.highlight = ('#0f8241')) + ggtitle('cocl2 second cells')
DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cis_cells, cells_per_condition$cistocis_cells, cells_per_condition$cistococl2_cells, cells_per_condition$cistodabtram_cells),
        cols.highlight = c('#a23622', '#f49129', '#fbd08c')) + ggtitle('cis first cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cis_cells, cells_per_condition$cistocis_cells, cells_per_condition$cistococl2_cells, cells_per_condition$cistodabtram_cells),
        cols.highlight = ('#c96d29')) + ggtitle('cis first cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cis_cells, cells_per_condition$cistocis_cells, cells_per_condition$cocl2tocis_cells, cells_per_condition$dabtramtocis_cells),
        cols.highlight = c('#9d85be', '#6dc49c', '#fbd08c')) + ggtitle('cis second cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cis_cells, cells_per_condition$cistocis_cells, cells_per_condition$cocl2tocis_cells, cells_per_condition$dabtramtocis_cells),
        cols.highlight = ('#c96d29')) + ggtitle('cis second cells')

Save the object to load in for distance metrics

save.image('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/workspace.RData')

Run distance metrics

save.image('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/workspace.RData')

Try pearson - https://pubmed.ncbi.nlm.nih.gov/30137247/

# Define manhatten distance function
manhattan.distance <- function(x, y) return(sum(abs(x-y)))

# Make metadata objects of the first and second conditions
second_timepoint$first_treatment <- sapply(strsplit(second_timepoint$OG_condition, "to"), "[[", 1)
second_timepoint$second_treatment <- sapply(strsplit(second_timepoint$OG_condition, "to"), "[[", 2)

# Get input data and subest
input_data <- GetAssayData(second_timepoint, assay = 'RNA', slot = 'scale.data')

# Number of cells for subsetting
num_cells <- 10000

# Look at grouping based on first sample
Idents(second_timepoint) <- second_timepoint$first_treatment
DimPlot(second_timepoint)


cocl2_first_cells <-  sample(names(second_timepoint$first_treatment)[second_timepoint$first_treatment == 'cocl2'], num_cells)
cocl2_first_subset <- input_data[,cocl2_first_cells]
cocl2_first_manhatten_distance <- CustomDistance(cocl2_first_subset, manhattan.distance)

dabtram_first_cells <-  sample(names(second_timepoint$first_treatment)[second_timepoint$first_treatment == 'dabtram'], num_cells)
dabtram_first_subset <- input_data[,dabtram_first_cells]
dabtram_first_manhatten_distance <- CustomDistance(dabtram_first_subset, manhattan.distance)

cis_first_cells <-  sample(names(second_timepoint$first_treatment)[second_timepoint$first_treatment == 'cis'], num_cells)
cis_first_subset <- input_data[,cis_first_cells]
cis_first_manhatten_distance <- CustomDistance(cis_first_subset, manhattan.distance)

Idents(second_timepoint) <- second_timepoint$second_treatment
DimPlot(second_timepoint)


cocl2_second_cells <-  sample(names(second_timepoint$second_treatment)[second_timepoint$second_treatment == 'cocl2'], num_cells)
cocl2_second_subset <- input_data[,cocl2_second_cells]
cocl2_second_manhatten_distance <- CustomDistance(cocl2_second_subset, manhattan.distance)

dabtram_second_cells <-  sample(names(second_timepoint$second_treatment)[second_timepoint$second_treatment == 'dabtram'], num_cells)
dabtram_second_subset <- input_data[,dabtram_second_cells]
dabtram_second_manhatten_distance <- CustomDistance(dabtram_second_subset, manhattan.distance)

cis_second_cells <-  sample(names(second_timepoint$second_treatment)[second_timepoint$second_treatment == 'cis'], num_cells)
cis_second_subset <- input_data[,cis_second_cells]
cis_second_manhatten_distance <- CustomDistance(cis_second_subset, manhattan.distance)

plotting_df <- data.frame(Grouping = c(rep('first',3*length(cis_first_manhatten_distance)),rep('second', 3*(length(cis_second_manhatten_distance)))),
                          Manhatten_dist <- c(cocl2_first_manhatten_distance, dabtram_first_manhatten_distance, cis_first_manhatten_distance, cocl2_second_manhatten_distance,dabtram_second_manhatten_distance, cis_second_manhatten_distance),
                          Treatment = c(rep('CoCl2 first',length(cocl2_first_manhatten_distance)),rep('Dab/Tram first',length(dabtram_first_manhatten_distance)),rep('Cisplatin first',length(cis_first_manhatten_distance)),rep('CoCl2 second',length(cocl2_second_manhatten_distance)),rep('Dab/Tram second',length(dabtram_second_manhatten_distance)),rep('Cisplatin second',length(cis_second_manhatten_distance))))

ggplot(plotting_df, aes(x = Treatment, y = Manhatten_dist, fill = Grouping)) + geom_violin() + geom_boxplot(width = 0.1)


save.image('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/workspace_v2.RData')

Statistical analysis and plotting of pearson metrics - CoCl2


#load('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/workspace_v2.RData')

rm(manhatten.distance, cocl2_first_manhatten_distance, dabtram_first_manhatten_distance, cis_first_manhatten_distance, cocl2_second_manhatten_distance, dabtram_second_manhatten_distance, cis_second_manhatten_distance)
Warning in rm(manhatten.distance, cocl2_first_manhatten_distance, dabtram_first_manhatten_distance,  :
  object 'manhatten.distance' not found
rm(cis, cistocis, cistococl2, cistodabtram, cocl2, cocl2tocis, cocl2tococl2, cocl2todabtram, dabtram, dabtramtocis, dabtramtococl2, dabtramtodabtram)
gc()
             used    (Mb) gc trigger    (Mb) limit (Mb)   max used    (Mb)
Ncells    4100917   219.1    6815804   364.1         NA    6815804   364.1
Vcells 1630180427 12437.3 7909077067 60341.5     102400 9886346333 75426.9
# Make metadata objects of the first and second conditions
second_timepoint$first_treatment <- sapply(strsplit(second_timepoint$OG_condition, "to"), "[[", 1)
second_timepoint$second_treatment <- sapply(strsplit(second_timepoint$OG_condition, "to"), "[[", 2)

# Get input data and subest
input_data <- GetAssayData(second_timepoint, assay = 'RNA', slot = 'scale.data')


# Look at grouping based on first sample
Idents(second_timepoint) <- second_timepoint$first_treatment
DimPlot(second_timepoint)


cocl2_first_cells <-  names(second_timepoint$first_treatment)[second_timepoint$first_treatment == 'cocl2']
cocl2_first_subset <- input_data[,cocl2_first_cells]
cocl2_first_pearson <- cor(cocl2_first_subset)
cocl2_first_pearson_filt <- cocl2_first_pearson[lower.tri(cocl2_first_pearson, diag = FALSE)]

set.seed(1)
cocl2_first_subset_rand <- input_data[,sample(colnames(input_data),length(cocl2_first_cells))]
cocl2_first_pearson_rand <- cor(cocl2_first_subset_rand)
cocl2_first_pearson_filt_rand <- cocl2_first_pearson_rand[lower.tri(cocl2_first_pearson_rand, diag = FALSE)]

dabtram_first_cells <-  names(second_timepoint$first_treatment)[second_timepoint$first_treatment == 'dabtram']
dabtram_first_subset <- input_data[,dabtram_first_cells]
dabtram_first_pearson <- cor(dabtram_first_subset)
dabtram_first_pearson_filt <- dabtram_first_pearson[lower.tri(dabtram_first_pearson, diag = FALSE)]

set.seed(1)
dabtram_first_subset_rand <- input_data[,sample(colnames(input_data),length(dabtram_first_cells))]
dabtram_first_pearson_rand <- cor(dabtram_first_subset_rand)
dabtram_first_pearson_filt_rand <- dabtram_first_pearson_rand[lower.tri(dabtram_first_pearson_rand, diag = FALSE)]

cis_first_cells <-  names(second_timepoint$first_treatment)[second_timepoint$first_treatment == 'cis']
cis_first_subset <- input_data[,cis_first_cells]
cis_first_pearson <- cor(cis_first_subset)
cis_first_pearson_filt <- cis_first_pearson[lower.tri(cis_first_pearson, diag = FALSE)]

set.seed(1)
cis_first_subset_rand <- input_data[,sample(colnames(input_data),length(cis_first_cells))]
cis_first_pearson_rand <- cor(cis_first_subset_rand)
cis_first_pearson_filt_rand <- cis_first_pearson_rand[lower.tri(cis_first_pearson_rand, diag = FALSE)]

Idents(second_timepoint) <- second_timepoint$second_treatment
DimPlot(second_timepoint)


cocl2_second_cells <-  names(second_timepoint$second_treatment)[second_timepoint$second_treatment == 'cocl2']
cocl2_second_subset <- input_data[,cocl2_second_cells]
cocl2_second_pearson <- cor(cocl2_second_subset)
cocl2_second_pearson_filt <- cocl2_second_pearson[lower.tri(cocl2_second_pearson, diag = FALSE)]

set.seed(1)
cocl2_second_subset_rand <- input_data[,sample(colnames(input_data),length(cocl2_second_cells))]
cocl2_second_pearson_rand <- cor(cocl2_second_subset_rand)
cocl2_second_pearson_filt_rand <- cocl2_second_pearson_rand[lower.tri(cocl2_second_pearson_rand, diag = FALSE)]

dabtram_second_cells <-  names(second_timepoint$second_treatment)[second_timepoint$second_treatment == 'dabtram']
dabtram_second_subset <- input_data[,dabtram_second_cells]
dabtram_second_pearson <- cor(dabtram_second_subset)
dabtram_second_pearson_filt <- dabtram_second_pearson[lower.tri(dabtram_second_pearson, diag = FALSE)]

set.seed(1)
dabtram_second_subset_rand <- input_data[,sample(colnames(input_data),length(dabtram_second_cells))]
dabtram_second_pearson_rand <- cor(dabtram_second_subset_rand)
dabtram_second_pearson_filt_rand <- dabtram_second_pearson_rand[lower.tri(dabtram_second_pearson_rand, diag = FALSE)]

cis_second_cells <-  names(second_timepoint$second_treatment)[second_timepoint$second_treatment == 'cis']
cis_second_subset <- input_data[,cis_second_cells]
cis_second_pearson <- cor(cis_second_subset)
cis_second_pearson_filt <- cis_second_pearson[lower.tri(cis_second_pearson, diag = FALSE)]

set.seed(1)
cis_second_subset_rand <- input_data[,sample(colnames(input_data),length(cis_second_cells))]
cis_second_pearson_rand <- cor(cis_second_subset_rand)
cis_second_pearson_filt_rand <- cis_second_pearson_rand[lower.tri(cis_second_pearson_rand, diag = FALSE)]

save.image('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/workspace_v3.RData')

# Save CoCl2 outputs
save(cocl2_first_pearson, cocl2_first_pearson_rand, cocl2_first_subset, cocl2_first_subset_rand, cocl2_first_pearson_filt, cocl2_first_pearson_filt_rand, cocl2_second_pearson, cocl2_second_pearson_rand, cocl2_second_subset, cocl2_second_subset_rand, cocl2_second_pearson_filt, cocl2_second_pearson_filt_rand, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cocl2_pearson_results.RData')
rm(cocl2_first_pearson, cocl2_first_pearson_rand, cocl2_first_subset, cocl2_first_subset_rand, cocl2_first_pearson_filt, cocl2_first_pearson_filt_rand, cocl2_second_pearson, cocl2_second_pearson_rand, cocl2_second_subset, cocl2_second_subset_rand, cocl2_second_pearson_filt, cocl2_second_pearson_filt_rand)

# Save dabtram outputs
save(dabtram_first_pearson, dabtram_first_pearson_rand, dabtram_first_subset, dabtram_first_subset_rand, dabtram_first_pearson_filt, dabtram_first_pearson_filt_rand, dabtram_second_pearson, dabtram_second_pearson_rand, dabtram_second_subset, dabtram_second_subset_rand, dabtram_second_pearson_filt, dabtram_second_pearson_filt_rand, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/dabtram_pearson_results.RData')
rm(dabtram_first_pearson, dabtram_first_pearson_rand, dabtram_first_subset, dabtram_first_subset_rand, dabtram_first_pearson_filt, dabtram_first_pearson_filt_rand, dabtram_second_pearson, dabtram_second_pearson_rand, dabtram_second_subset, dabtram_second_subset_rand, dabtram_second_pearson_filt, dabtram_second_pearson_filt_rand)

# Save cis outputs
save(cis_first_pearson, cis_first_pearson_rand, cis_first_subset, cis_first_subset_rand, cis_first_pearson_filt, cis_first_pearson_filt_rand, cis_second_pearson, cis_second_pearson_rand, cis_second_subset, cis_second_subset_rand, cis_second_pearson_filt, cis_second_pearson_filt_rand, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cis_pearson_results.RData')
rm(cis_first_pearson, cis_first_pearson_rand, cis_first_subset, cis_first_subset_rand, cis_first_pearson_filt, cis_first_pearson_filt_rand, cis_second_pearson, cis_second_pearson_rand, cis_second_subset, cis_second_subset_rand, cis_second_pearson_filt, cis_second_pearson_filt_rand)

Statistical analysis and plotting of pearson metrics - dabtram

load('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cocl2_pearson_results.RData') # Load data

pearson_ttest_cocl2_firstvsrand <- t.test(cocl2_first_pearson_filt, cocl2_first_pearson_filt_rand,  paired = F)
pearson_ttest_cocl2_secondvsrand <- t.test(cocl2_second_pearson_filt, cocl2_second_pearson_filt_rand,  paired = F)
pearson_ttest_cocl2_secondvsfirst <- t.test(cocl2_second_pearson_filt, cocl2_first_pearson_filt,  paired = F)
pearson_ttest_cocl2_randvsrand <- t.test(cocl2_second_pearson_filt_rand, cocl2_first_pearson_filt_rand,  paired = F)

rm(cocl2_first_pearson, cocl2_first_pearson_rand, cocl2_first_subset, cocl2_first_subset_rand, cocl2_second_pearson, cocl2_second_pearson_rand, cocl2_second_subset, cocl2_second_subset_rand)

plotting_df_pearson_cocl2 <- data.frame(Grouping = c(rep('first',length(cocl2_first_pearson_filt)), rep('random',length(cocl2_first_pearson_filt)), rep('second', length(cocl2_second_pearson_filt)), rep('random', length(cocl2_second_pearson_filt))),
                          Pearson = c(cocl2_first_pearson_filt, cocl2_first_pearson_filt_rand, cocl2_second_pearson_filt, cocl2_second_pearson_filt_rand),
                          Treatment = c(rep('CoCl2 first',length(cocl2_first_pearson_filt)), rep('CoCl2 first rand', length(cocl2_first_pearson_filt_rand)),rep('CoCl2 second',length(cocl2_second_pearson_filt)),rep('CoCl2 second rand',length(cocl2_second_pearson_filt_rand))))
colnames(plotting_df_pearson_cocl2) <- c('Grouping','Pearson','Treatment')

rm(cocl2_first_pearson_filt, cocl2_first_pearson_filt_rand, cocl2_second_pearson_filt, cocl2_second_pearson_filt_rand)
gc()
             used    (Mb)  gc trigger    (Mb) limit (Mb)    max used    (Mb)
Ncells    4102976   219.2     6815804   364.1         NA     6815804   364.1
Vcells 5659627351 43179.6 11389246976 86893.1     102400 11355547725 86636.0
pdf('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cocl2_pearson_plot_subsampled.pdf')
set.seed(1)
ggplot(plotting_df_pearson_cocl2[sample(1:nrow(plotting_df_pearson_cocl2), 10000000),], aes(x = Treatment, y = Pearson, fill = Grouping)) + geom_violin() + geom_boxplot(width = 0.1, outlier.shape = NA) +
  scale_fill_manual(values=c("#FF0000", "#D3D3D3", "#0000FF"))
dev.off()
null device 
          1 
# Save outputs
save(pearson_ttest_cocl2_firstvsrand, pearson_ttest_cocl2_secondvsfirst, pearson_ttest_cocl2_secondvsrand, pearson_ttest_cocl2_randvsrand, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cocl2_pearson_values.RData')
rm(pearson_ttest_cocl2_firstvsrand, pearson_ttest_cocl2_secondvsfirst, pearson_ttest_cocl2_secondvsrand, pearson_ttest_cocl2_randvsrand)

save(plotting_df_pearson_cocl2, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cocl2_pearson_plotting_df.RData')
rm(plotting_df_pearson_cocl2)

Statistical analysis and plotting of pearson metrics - cis

load('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/dabtram_pearson_results.RData') # Load data

pearson_ttest_dabtram_firstvsrand <- t.test(dabtram_first_pearson_filt, dabtram_first_pearson_filt_rand,  paired = F)
pearson_ttest_dabtram_secondvsrand <- t.test(dabtram_second_pearson_filt, dabtram_second_pearson_filt_rand,  paired = F)
pearson_ttest_dabtram_secondvsfirst <- t.test(dabtram_second_pearson_filt, dabtram_first_pearson_filt,  paired = F)
pearson_ttest_dabtram_randvsrand <- t.test(dabtram_second_pearson_filt_rand, dabtram_first_pearson_filt_rand,  paired = F)

rm(dabtram_first_pearson, dabtram_first_pearson_rand, dabtram_first_subset, dabtram_first_subset_rand, dabtram_second_pearson, dabtram_second_pearson_rand, dabtram_second_subset, dabtram_second_subset_rand)

plotting_df_pearson_dabtram <- data.frame(Grouping = c(rep('first',length(dabtram_first_pearson_filt)), rep('random',length(dabtram_first_pearson_filt)), rep('second', length(dabtram_second_pearson_filt)), rep('random', length(dabtram_second_pearson_filt))),
                          Pearson = c(dabtram_first_pearson_filt, dabtram_first_pearson_filt_rand, dabtram_second_pearson_filt, dabtram_second_pearson_filt_rand),
                          Treatment = c(rep('dabtram first',length(dabtram_first_pearson_filt)), rep('dabtram first rand', length(dabtram_first_pearson_filt_rand)),rep('dabtram second',length(dabtram_second_pearson_filt)),rep('dabtram second rand',length(dabtram_second_pearson_filt_rand))))
colnames(plotting_df_pearson_dabtram) <- c('Grouping','Pearson','Treatment')

rm(dabtram_first_pearson_filt, dabtram_first_pearson_filt_rand, dabtram_second_pearson_filt, dabtram_second_pearson_filt_rand)
gc()
             used    (Mb)  gc trigger    (Mb) limit (Mb)    max used    (Mb)
Ncells    4102712   219.2     6815804   364.1         NA     6815804   364.1
Vcells 3678842165 28067.4 11389246976 86893.1     102400 11361287181 86679.8
pdf('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/dabtram_pearson_plot_subsampled.pdf')
set.seed(1)
ggplot(plotting_df_pearson_dabtram[sample(1:nrow(plotting_df_pearson_dabtram), 10000000),], aes(x = Treatment, y = Pearson, fill = Grouping)) + geom_violin() + geom_boxplot(width = 0.1, outlier.shape = NA) +
  scale_fill_manual(values=c("#FF0000", "#D3D3D3", "#0000FF"))
dev.off()
null device 
          1 
# Save outputs
save(pearson_ttest_dabtram_firstvsrand, pearson_ttest_dabtram_secondvsfirst, pearson_ttest_dabtram_secondvsrand,pearson_ttest_dabtram_randvsrand, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/dabtram_pearson_values.RData')
rm(pearson_ttest_dabtram_firstvsrand, pearson_ttest_dabtram_secondvsfirst, pearson_ttest_dabtram_secondvsrand, pearson_ttest_dabtram_randvsrand)

save(plotting_df_pearson_dabtram, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/dabtram_pearson_plotting_df.RData')
rm(plotting_df_pearson_dabtram)

Load in the ttest data and compile into excel sheet

load('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cis_pearson_results.RData') # Load data

pearson_ttest_cis_firstvsrand <- t.test(cis_first_pearson_filt, cis_first_pearson_filt_rand,  paired = F)
pearson_ttest_cis_secondvsrand <- t.test(cis_second_pearson_filt, cis_second_pearson_filt_rand,  paired = F)
pearson_ttest_cis_secondvsfirst <- t.test(cis_second_pearson_filt, cis_first_pearson_filt,  paired = F)
pearson_ttest_cis_randvsrand <- t.test(cis_second_pearson_filt_rand, cis_first_pearson_filt_rand,  paired = F)

rm(cis_first_pearson, cis_first_pearson_rand, cis_first_subset, cis_first_subset_rand, cis_second_pearson, cis_second_pearson_rand, cis_second_subset, cis_second_subset_rand)

plotting_df_pearson_cis <- data.frame(Grouping = c(rep('first',length(cis_first_pearson_filt)), rep('random',length(cis_first_pearson_filt)), rep('second', length(cis_second_pearson_filt)), rep('random', length(cis_second_pearson_filt))),
                          Pearson = c(cis_first_pearson_filt, cis_first_pearson_filt_rand, cis_second_pearson_filt, cis_second_pearson_filt_rand),
                          Treatment = c(rep('cis first',length(cis_first_pearson_filt)), rep('cis first rand', length(cis_first_pearson_filt_rand)),rep('cis second',length(cis_second_pearson_filt)),rep('cis second rand',length(cis_second_pearson_filt_rand))))
colnames(plotting_df_pearson_cis) <- c('Grouping','Pearson','Treatment')

rm(cis_first_pearson_filt, cis_first_pearson_filt_rand, cis_second_pearson_filt, cis_second_pearson_filt_rand)
gc()
             used    (Mb) gc trigger    (Mb) limit (Mb)    max used    (Mb)
Ncells    4102791   219.2    6815804   364.1         NA     6815804   364.1
Vcells 2804429888 21396.2 9111397581 69514.5     102400 11361287181 86679.8
pdf('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cis_pearson_plot_subsampled.pdf')
set.seed(1)
ggplot(plotting_df_pearson_cis[sample(1:nrow(plotting_df_pearson_cis), 10000000),], aes(x = Treatment, y = Pearson, fill = Grouping)) + geom_violin() + geom_boxplot(width = 0.1, outlier.shape = NA) +
  scale_fill_manual(values=c("#FF0000", "#D3D3D3", "#0000FF"))
dev.off()
null device 
          1 
# Save outputs
save(pearson_ttest_cis_firstvsrand, pearson_ttest_cis_secondvsfirst, pearson_ttest_cis_secondvsrand, pearson_ttest_cis_randvsrand, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cis_pearson_values.RData')
rm(pearson_ttest_cis_firstvsrand, pearson_ttest_cis_secondvsfirst, pearson_ttest_cis_secondvsrand, pearson_ttest_cis_randvsrand)

save(plotting_df_pearson_cis, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cis_pearson_plotting_df.RData')
rm(plotting_df_pearson_cis)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQojSU1QT1JUQU5UIE5PVEU6IGV2ZXJ5dGhpbmcgZm9yIHBsb3R0aW5nIGluIGZpZ3VyZXMgY3VycmVudGx5IGNvbWVzIGZyb20gdGhlIHNlY29uZF90aW1lcG9pbnQgb2JqZWN0LCBidXQgdGhlcmUgYXJlIGFkZGl0aW9uYWwgY2h1bmtzIHRoYXQgcnVuIHNpbWlsYXIgYW5hbHlzZXMgb24gYWxsX2RhdGEgb2JqZWN0cyB3aXRoIGRpZmZlcmVudCBjbHVzdGVyIG51bWJlcnMKCgojU2V0IHdvcmtpbmcgZGlyZWN0b3J5IHRvIGFwcHJvcHJpYXRlIGZvbGRlciBmb3IgaW5wdXRzIGFuZCBvdXRwdXRzIG9uIEdvb2dsZSBEcml2ZQpgYGB7ciwgc2V0dXAsIGluY2x1ZGU9RkFMU0V9CiNrbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9ICcvVm9sdW1lcy9Hb29nbGVEcml2ZS9NeSBEcml2ZS9GYXNzZV9TaGFyZWQvQUpGX0RyaXZlX2NvcHkvRXhwZXJpbWVudHMvQUpGMDA5JykgIyBmb3IgYXJpYSdzIGNvbXB1dGVyCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gJy9Vc2Vycy9keWxhbnNjaGFmZi9MaWJyYXJ5L0Nsb3VkU3RvcmFnZS9Hb29nbGVEcml2ZS1keXNjaGFmZkBzeWRzaGFmZmVybGFiLmNvbS9NeSBEcml2ZS9GYXNzZV9TaGFyZWQvQUpGX0RyaXZlX2NvcHkvRXhwZXJpbWVudHMvQUpGMDA5JykgIyBmb3IgZHlsYW4ncyBjb21wdXRlcgoKIzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nLyBpcyBhZGRpdGlvbmFsIHBhdGggZm9yIG91dHB1dHMKCmBgYAoKI0luaXRpYWxpemUKYGBge3IgaW5jbHVkZSA9IEZBTFNFfQpybShsaXN0ID0gbHMoKSkKbGlicmFyeShkcGx5cikKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkoeGxzeCkKYGBgCgojIExvYWQgZGF0YQpgYGB7cn0KbG9hZCgnMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvUHJlcHJvY2Vzc19HRVgvT2JqZWN0c19wcmVtZXJnZWQuUkRhdGEnKQpsb2FkKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9QcmVwcm9jZXNzX0dFWC9zZWNvbmRfdGltZXBvaW50X21lcmdlZC5SRGF0YScpCmxvYWQoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL1ByZXByb2Nlc3NfR0VYL2ZpcnN0X3RpbWVwb2ludF9tZXJnZWQuUkRhdGEnKQpgYGAKCiMgY2x1c3RlciBzZWNvbmQgdGltZXBvaW50IGFuZCBwbG90CmBgYHtyfQpzZWNvbmRfdGltZXBvaW50IDwtIE5vcm1hbGl6ZURhdGEoc2Vjb25kX3RpbWVwb2ludCkKc2Vjb25kX3RpbWVwb2ludCA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhzZWNvbmRfdGltZXBvaW50LCBzZWxlY3Rpb24ubWV0aG9kID0gJ3ZzdCcsIG5GZWF0dXJlcyA9IDIwMDAwKQpzZWNvbmRfdGltZXBvaW50IDwtIFNjYWxlRGF0YShzZWNvbmRfdGltZXBvaW50KQpzZWNvbmRfdGltZXBvaW50IDwtIFJ1blBDQShzZWNvbmRfdGltZXBvaW50KQpzZWNvbmRfdGltZXBvaW50IDwtIEZpbmROZWlnaGJvcnMoc2Vjb25kX3RpbWVwb2ludCwgZGltcyA9IDE6MTUpCnNlY29uZF90aW1lcG9pbnQgPC0gRmluZENsdXN0ZXJzKHNlY29uZF90aW1lcG9pbnQsIHJlc29sdXRpb24gPSAwLjUpCnNlY29uZF90aW1lcG9pbnQgPC0gUnVuVU1BUChzZWNvbmRfdGltZXBvaW50LCBkaW1zID0gMToxNSkKCmNlbGxzX3Blcl9jbHVzdGVyIDwtIGRhdGEuZnJhbWUgKENsdXN0ZXIgPSBhcy5udW1lcmljKHNlY29uZF90aW1lcG9pbnQkc2V1cmF0X2NsdXN0ZXJzKSwgQ29uZGl0aW9uID0gc2Vjb25kX3RpbWVwb2ludCRPR19jb25kaXRpb24pCmNlbGxzX3Blcl9jbHVzdGVyX2xpc3QgPC0gbGlzdCgpCgpwZGYoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL29yaWdpbmFsX2NvbmRpdGlvbl9zZWNvbmRfdGltZXBvaW50LnBkZicpCnByaW50KERpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCkpCnByaW50KERpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgbGFiZWwgPSBULCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBjb2xzID0gYygnZGFidHJhbXRvZGFidHJhbScgPSAnIzU2MUU1OScsICdkYWJ0cmFtdG9jb2NsMicgPSAnI0EyMjQ4RScsICdkYWJ0cmFtdG9jaXMnID0gJyM5RDg1QkUnLCAnY29jbDJ0b2RhYnRyYW0nID0gJyMxMDQxM0InLCAnY29jbDJ0b2NvY2wyJyA9ICcjNkFCRDQ1JywgJ2NvY2wydG9jaXMnID0gJyM2REM0OUMnLCAnY2lzdG9kYWJ0cmFtJyA9ICcjQTIzNjIyJywgJ2Npc3RvY29jbDInID0gJyNGNDkxMjknLCAnY2lzdG9jaXMnID0gJyNGQkQwOEMnKSkpCgpmb3IgKGkgaW4gMToobWF4KGNlbGxzX3Blcl9jbHVzdGVyJENsdXN0ZXIpKSl7CiAgY3VycmVudGNsdXN0ZXIgPC0gZmlsdGVyKGNlbGxzX3Blcl9jbHVzdGVyLCBjZWxsc19wZXJfY2x1c3RlciRDbHVzdGVyID09IGkpCiAgY2VsbHNfcGVyX2NsdXN0ZXJfbGlzdFtbcGFzdGUwKCdDbHVzdGVyJywgaSldXSA8LSBkYXRhLmZyYW1lKHRhYmxlKGN1cnJlbnRjbHVzdGVyJENvbmRpdGlvbikpCiAgCiAgcHJpbnQoZ2dwbG90KGNlbGxzX3Blcl9jbHVzdGVyX2xpc3RbW3Bhc3RlMCgnQ2x1c3RlcicsIGkpXV0sIGFlcyh4ID0nJywgeSA9IEZyZXEsIGZpbGwgPSBWYXIxKSkgKyBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKyBjb29yZF9wb2xhcigneScsIHN0YXJ0ID0gMCkgKyB0aGVtZV92b2lkKCkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCdkYWJ0cmFtdG9kYWJ0cmFtJyA9ICcjNTYxRTU5JywgJ2RhYnRyYW10b2NvY2wyJyA9ICcjQTIyNDhFJywgJ2RhYnRyYW10b2NpcycgPSAnIzlEODVCRScsICdjb2NsMnRvZGFidHJhbScgPSAnIzEwNDEzQicsICdjb2NsMnRvY29jbDInID0gJyM2QUJENDUnLCAnY29jbDJ0b2NpcycgPSAnIzZEQzQ5QycsICdjaXN0b2RhYnRyYW0nID0gJyNBMjM2MjInLCAnY2lzdG9jb2NsMicgPSAnI0Y0OTEyOScsICdjaXN0b2NpcycgPSAnI0ZCRDA4QycpKSArIGxhYnModGl0bGUgPSBwYXN0ZSgnT3JpZ2luYWwgY29uZGl0aW9uIG9mIGNlbGxzIGluIGNsdXN0ZXInLCBpLTEpKSkKfQpkZXYub2ZmKCkKCmBgYAoKIyBUaGlzIGlzIHRoZSBzYW1lIGNodW5rIGFzIGFib3ZlIGJ1dCBpdCBtYWtlcyB0aGUgcGxvdHMgYXMgYmFyIGNoYXJ0cyBpbiBpbmRpdmlkdWFsIFBERnMgZm9yIHB1bGxpbmcgaW50byBpbGx1c3RyYXRvcgpgYGB7cn0KCmNlbGxzX3Blcl9jbHVzdGVyIDwtIGRhdGEuZnJhbWUgKENsdXN0ZXIgPSBhcy5udW1lcmljKHNlY29uZF90aW1lcG9pbnQkc2V1cmF0X2NsdXN0ZXJzKSwgQ29uZGl0aW9uID0gc2Vjb25kX3RpbWVwb2ludCRPR19jb25kaXRpb24pCmNlbGxzX3Blcl9jbHVzdGVyX2xpc3QgPC0gbGlzdCgpCgpmb3IgKGkgaW4gMToobWF4KGNlbGxzX3Blcl9jbHVzdGVyJENsdXN0ZXIpKSl7CiAgcGRmKHBhc3RlMCgnMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvb3JpZ2luYWxfY29uZGl0aW9uX3NlY29uZF90aW1lcG9pbnRfY2x1c3RlcicsIGktMSwgJy5wZGYnKSkKICBjdXJyZW50Y2x1c3RlciA8LSBmaWx0ZXIoY2VsbHNfcGVyX2NsdXN0ZXIsIGNlbGxzX3Blcl9jbHVzdGVyJENsdXN0ZXIgPT0gaSkKICBjZWxsc19wZXJfY2x1c3Rlcl9saXN0W1twYXN0ZTAoJ0NsdXN0ZXInLCBpKV1dIDwtIGRhdGEuZnJhbWUodGFibGUoY3VycmVudGNsdXN0ZXIkQ29uZGl0aW9uKSkKICAKICBwcmludChnZ3Bsb3QoY2VsbHNfcGVyX2NsdXN0ZXJfbGlzdFtbcGFzdGUwKCdDbHVzdGVyJywgaSldXSwgYWVzKHggPScnLCB5ID0gRnJlcSwgZmlsbCA9IFZhcjEpKSArIGdlb21fYmFyKHBvc2l0aW9uID0gJ2ZpbGwnLCBzdGF0ID0gJ2lkZW50aXR5JykgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCdkYWJ0cmFtJyA9ICcjNjIzNTk0JywgJ2NvY2wyJyA9ICcjMEY4MjQxJywgJ2NpcycgPSAnI0M5NkQyOScsICdkYWJ0cmFtdG9kYWJ0cmFtJyA9ICcjNTYxRTU5JywgJ2RhYnRyYW10b2NvY2wyJyA9ICcjQTIyNDhFJywgJ2RhYnRyYW10b2NpcycgPSAnIzlEODVCRScsICdjb2NsMnRvZGFidHJhbScgPSAnIzEwNDEzQicsICdjb2NsMnRvY29jbDInID0gJyM2QUJENDUnLCAnY29jbDJ0b2NpcycgPSAnIzZEQzQ5QycsICdjaXN0b2RhYnRyYW0nID0gJyNBMjM2MjInLCAnY2lzdG9jb2NsMicgPSAnI0Y0OTEyOScsICdjaXN0b2NpcycgPSAnI0ZCRDA4QycpKSArIGxhYnModGl0bGUgPSBwYXN0ZSgnT3JpZ2luYWwgY29uZGl0aW9uIG9mIGNlbGxzIGluIHNlY29uZCB0aW1lcG9pbnQgY2x1c3RlcicsIGktMSkpKQogIGRldi5vZmYoKQp9CmBgYAoKI2VkaXRpbmcgY2VsbHNfcGVyX2NsdXN0ZXIgc28gdGhhdCB0aGUgY29uZGl0aW9uIG5hbWUgaXMgd2hhdGV2ZXIgc2Vjb25kIGNvbmRpdGlvbgpgYGB7ciBpbmNsdWRlID0gRkFMU0V9CgpjZWxsc19wZXJfY2x1c3Rlcl9zZWNvbmRkcnVnIDwtIGNlbGxzX3Blcl9jbHVzdGVyCmNlbGxzX3Blcl9jbHVzdGVyX2ZpcnN0ZHJ1ZyA8LSBjZWxsc19wZXJfY2x1c3RlcgoKZm9yIChpIGluIDE6bnJvdyhjZWxsc19wZXJfY2x1c3RlcikpewogIGlmIChjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiZGFidHJhbXRvZGFidHJhbSIgfHwgY2VsbHNfcGVyX2NsdXN0ZXIkQ29uZGl0aW9uW1tpXV0gPT0gImNpc3RvZGFidHJhbSIgfHwgY2VsbHNfcGVyX2NsdXN0ZXIkQ29uZGl0aW9uW1tpXV0gPT0gImNvY2wydG9kYWJ0cmFtIikgewogICAgY2VsbHNfcGVyX2NsdXN0ZXJfc2Vjb25kZHJ1ZyRDb25kaXRpb25bW2ldXSA8LSAiZGFidHJhbXNlY29uZCIKICB9CiAgaWYgKGNlbGxzX3Blcl9jbHVzdGVyJENvbmRpdGlvbltbaV1dID09ICJjb2NsMnRvY29jbDIiIHx8IGNlbGxzX3Blcl9jbHVzdGVyJENvbmRpdGlvbltbaV1dID09ICJjaXN0b2NvY2wyIiB8fCBjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiZGFidHJhbXRvY29jbDIiKSB7CiAgICBjZWxsc19wZXJfY2x1c3Rlcl9zZWNvbmRkcnVnJENvbmRpdGlvbltbaV1dIDwtICJjb2NsMnNlY29uZCIKICB9CiAgaWYgKGNlbGxzX3Blcl9jbHVzdGVyJENvbmRpdGlvbltbaV1dID09ICJjaXN0b2NpcyIgfHwgY2VsbHNfcGVyX2NsdXN0ZXIkQ29uZGl0aW9uW1tpXV0gPT0gImNvY2wydG9jaXMiIHx8IGNlbGxzX3Blcl9jbHVzdGVyJENvbmRpdGlvbltbaV1dID09ICJkYWJ0cmFtdG9jaXMiKSB7CiAgICBjZWxsc19wZXJfY2x1c3Rlcl9zZWNvbmRkcnVnJENvbmRpdGlvbltbaV1dIDwtICJjaXNzZWNvbmQiCiAgfQp9Cgpmb3IgKGkgaW4gMTpucm93KGNlbGxzX3Blcl9jbHVzdGVyKSl7CiAgaWYgKGNlbGxzX3Blcl9jbHVzdGVyJENvbmRpdGlvbltbaV1dID09ICJkYWJ0cmFtdG9kYWJ0cmFtIiB8fCBjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiZGFidHJhbXRvY2lzIiB8fCBjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiZGFidHJhbXRvY29jbDIiKSB7CiAgICBjZWxsc19wZXJfY2x1c3Rlcl9maXJzdGRydWckQ29uZGl0aW9uW1tpXV0gPC0gImRhYnRyYW1maXJzdCIKICB9CiAgaWYgKGNlbGxzX3Blcl9jbHVzdGVyJENvbmRpdGlvbltbaV1dID09ICJjb2NsMnRvY29jbDIiIHx8IGNlbGxzX3Blcl9jbHVzdGVyJENvbmRpdGlvbltbaV1dID09ICJjb2NsMnRvY2lzIiB8fCBjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiY29jbDJ0b2RhYnRyYW0iKSB7CiAgICBjZWxsc19wZXJfY2x1c3Rlcl9maXJzdGRydWckQ29uZGl0aW9uW1tpXV0gPC0gImNvY2wyZmlyc3QiCiAgfQogIGlmIChjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiY2lzdG9jaXMiIHx8IGNlbGxzX3Blcl9jbHVzdGVyJENvbmRpdGlvbltbaV1dID09ICJjaXN0b2NvY2wyIiB8fCBjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiY2lzdG9kYWJ0cmFtIikgewogICAgY2VsbHNfcGVyX2NsdXN0ZXJfZmlyc3RkcnVnJENvbmRpdGlvbltbaV1dIDwtICJjaXNmaXJzdCIKICB9Cn0KCiNub3cgY29sb3JlZCBiYXNlZCBvbiBzZWNvbmQgZHJ1ZyBvbmx5CmZvciAoaSBpbiAxOihtYXgoY2VsbHNfcGVyX2NsdXN0ZXJfc2Vjb25kZHJ1ZyRDbHVzdGVyKSkpewogIHBkZihwYXN0ZTAoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2VuZF9jb25kaXRpb25fc2Vjb25kX3RpbWVwb2ludCcsIGktMSwgJy5wZGYnKSkKICBjdXJyZW50Y2x1c3RlciA8LSBmaWx0ZXIoY2VsbHNfcGVyX2NsdXN0ZXJfc2Vjb25kZHJ1ZywgY2VsbHNfcGVyX2NsdXN0ZXJfc2Vjb25kZHJ1ZyRDbHVzdGVyID09IGkpCiAgY2VsbHNfcGVyX2NsdXN0ZXJfbGlzdFtbcGFzdGUwKCdDbHVzdGVyJywgaSldXSA8LSBkYXRhLmZyYW1lKHRhYmxlKGN1cnJlbnRjbHVzdGVyJENvbmRpdGlvbikpCiAgCiAgcHJpbnQoZ2dwbG90KGNlbGxzX3Blcl9jbHVzdGVyX2xpc3RbW3Bhc3RlMCgnQ2x1c3RlcicsIGkpXV0sIGFlcyh4ID0nJywgeSA9IEZyZXEsIGZpbGwgPSBWYXIxKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICdmaWxsJywgc3RhdCA9ICdpZGVudGl0eScpICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygnZGFidHJhbXNlY29uZCcgPSAnIzYyMzU5NCcsICdjb2NsMnNlY29uZCcgPSAnIzBGODI0MScsICdjaXNzZWNvbmQnID0gJyNDOTZEMjknKSkgKyBsYWJzKHRpdGxlID0gcGFzdGUoJ0VuZCBjb25kaXRpb24gb2YgY2VsbHMgaW4gc2Vjb25kIHRpbWVwb2ludCBjbHVzdGVyJywgaS0xKSkpCiAgZGV2Lm9mZigpCn0KCiNub3cgY29sb3JlZCBiYXNlZCBvbiBmaXJzdCBkcnVnIG9ubHkKZm9yIChpIGluIDE6KG1heChjZWxsc19wZXJfY2x1c3Rlcl9maXJzdGRydWckQ2x1c3RlcikpKXsKICBwZGYocGFzdGUwKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9maXJzdF9jb25kaXRpb25fc2Vjb25kX3RpbWVwb2ludCcsIGktMSwgJy5wZGYnKSkKICBjdXJyZW50Y2x1c3RlciA8LSBmaWx0ZXIoY2VsbHNfcGVyX2NsdXN0ZXJfZmlyc3RkcnVnLCBjZWxsc19wZXJfY2x1c3Rlcl9maXJzdGRydWckQ2x1c3RlciA9PSBpKQogIGNlbGxzX3Blcl9jbHVzdGVyX2xpc3RbW3Bhc3RlMCgnQ2x1c3RlcicsIGkpXV0gPC0gZGF0YS5mcmFtZSh0YWJsZShjdXJyZW50Y2x1c3RlciRDb25kaXRpb24pKQogIAogIHByaW50KGdncGxvdChjZWxsc19wZXJfY2x1c3Rlcl9saXN0W1twYXN0ZTAoJ0NsdXN0ZXInLCBpKV1dLCBhZXMoeCA9JycsIHkgPSBGcmVxLCBmaWxsID0gVmFyMSkpICsgZ2VvbV9iYXIocG9zaXRpb24gPSAnZmlsbCcsIHN0YXQgPSAnaWRlbnRpdHknKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoJ2RhYnRyYW1maXJzdCcgPSAnIzYyMzU5NCcsICdjb2NsMmZpcnN0JyA9ICcjMEY4MjQxJywgJ2Npc2ZpcnN0JyA9ICcjQzk2RDI5JykpICsgbGFicyh0aXRsZSA9IHBhc3RlKCdFbmQgY29uZGl0aW9uIG9mIGNlbGxzIGluIGZpcnN0IHRpbWVwb2ludCBjbHVzdGVyJywgaS0xKSkpCiAgZGV2Lm9mZigpCn0KYGBgCgojVU1BUHMgaGlnaGxpZ2h0aW5nIGFsbCBjZWxscyB0aGF0IGhhZCBzYW1lIGZpcnN0IGFuZCBzZWNvbmQgZHJ1ZyBpbiBzZWNvbmRfdGltZXBvaW50IG9iamVjdApgYGB7cn0KY2VsbHNfcGVyX2NvbmRpdGlvbiA8LSBsaXN0KCkKZm9yIChpIGluIGMoJ2RhYnRyYW10b2RhYnRyYW0nLCAnZGFidHJhbXRvY29jbDInLCAnZGFidHJhbXRvY2lzJywgJ2NvY2wydG9kYWJ0cmFtJywgJ2NvY2wydG9jb2NsMicsICdjb2NsMnRvY2lzJywgJ2Npc3RvZGFidHJhbScsICdjaXN0b2NvY2wyJywgJ2Npc3RvY2lzJykpewogIGNlbGxzX3Blcl9jb25kaXRpb25bW3Bhc3RlMChpLCAnX2NlbGxzJyldXSA8LSBuYW1lcyhzZWNvbmRfdGltZXBvaW50JG9yaWcuaWRlbnRbc2Vjb25kX3RpbWVwb2ludCRPR19jb25kaXRpb24gPT0gaV0pCn0KCnBkZignMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvZHJ1Z19ncm91cF9oaWdobGlnaHRzLnBkZicpCgpEaW1QbG90KHNlY29uZF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgcHQuc2l6ZSA9IC4xLAogICAgICAgIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3QoY2VsbHNfcGVyX2NvbmRpdGlvbiRkYWJ0cmFtdG9kYWJ0cmFtX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGRhYnRyYW10b2Npc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRkYWJ0cmFtdG9jb2NsMl9jZWxscyksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSAoJ3JlZCcpKSArIGdndGl0bGUoJ2RhYnRyYW0gZmlyc3QgY2VsbHMnKQpEaW1QbG90KHNlY29uZF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgcHQuc2l6ZSA9IC4xLAogICAgICAgIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3QoY2VsbHNfcGVyX2NvbmRpdGlvbiRjb2NsMnRvY29jbDJfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY29jbDJ0b2Npc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjb2NsMnRvZGFidHJhbV9jZWxscyksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSAoJ3JlZCcpKSArIGdndGl0bGUoJ2NvY2wyIGZpcnN0IGNlbGxzJykKRGltUGxvdChzZWNvbmRfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KGNlbGxzX3Blcl9jb25kaXRpb24kY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvY29jbDJfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY2lzdG9kYWJ0cmFtX2NlbGxzKSwKICAgICAgICBjb2xzLmhpZ2hsaWdodCA9ICgncmVkJykpICsgZ2d0aXRsZSgnY2lzIGZpcnN0IGNlbGxzJykKCkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChjZWxsc19wZXJfY29uZGl0aW9uJGRhYnRyYW10b2RhYnRyYW1fY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY2lzdG9kYWJ0cmFtX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNvY2wydG9kYWJ0cmFtX2NlbGxzKSwKICAgICAgICBjb2xzLmhpZ2hsaWdodCA9ICgnYmx1ZScpKSArIGdndGl0bGUoJ2RhYnRyYW0gc2Vjb25kIGNlbGxzJykKRGltUGxvdChzZWNvbmRfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KGNlbGxzX3Blcl9jb25kaXRpb24kY29jbDJ0b2NvY2wyX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvY29jbDJfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kZGFidHJhbXRvY29jbDJfY2VsbHMpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gKCdibHVlJykpICsgZ2d0aXRsZSgnY29jbDIgc2Vjb25kIGNlbGxzJykKRGltUGxvdChzZWNvbmRfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KGNlbGxzX3Blcl9jb25kaXRpb24kY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNvY2wydG9jaXNfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kZGFidHJhbXRvY2lzX2NlbGxzKSwKICAgICAgICBjb2xzLmhpZ2hsaWdodCA9ICgnYmx1ZScpKSArIGdndGl0bGUoJ2NpcyBzZWNvbmQgY2VsbHMnKQoKZGV2Lm9mZigpCmBgYAoKI1VNQVBzIGhpZ2hsaWdodGluZyBhbGwgY2VsbHMgdGhhdCBoYWQgc2FtZSBmaXJzdCBkcnVnIGluIGZpcnN0X3RpbWVwb2ludCBvYmplY3QKYGBge3J9CnBkZignMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvZHJ1Z19ncm91cF9oaWdobGlnaHRzX2ZpcnN0X3RpbWVwb2ludC5wZGYnKQoKRGltUGxvdChmaXJzdF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAiT0dfY29uZGl0aW9uIiwgcHQuc2l6ZSA9IDIsIGNvbHMgPSAgYygnZGFidHJhbScgPSAnIzYyMzU5NCcsICdjb2NsMicgPSAnIzBGODI0MScsICdjaXMnID0gJyNDOTZEMjknKSkKRGltUGxvdChmaXJzdF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgcHQuc2l6ZSA9IC4xLAogICAgICAgIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3QobmFtZXMoZmlyc3RfdGltZXBvaW50JG9yaWcuaWRlbnRbZmlyc3RfdGltZXBvaW50JE9HX2NvbmRpdGlvbiA9PSAnZGFidHJhbSddKSksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSAoJ3JlZCcpKSArIGdndGl0bGUoJ2RhYnRyYW0gZmlyc3QgY2VsbHMnKQpEaW1QbG90KGZpcnN0X3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChuYW1lcyhmaXJzdF90aW1lcG9pbnQkb3JpZy5pZGVudFtmaXJzdF90aW1lcG9pbnQkT0dfY29uZGl0aW9uID09ICdjb2NsMiddKSksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSAoJ3JlZCcpKSArIGdndGl0bGUoJ2NvY2wyIGZpcnN0IGNlbGxzJykKRGltUGxvdChmaXJzdF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgcHQuc2l6ZSA9IC4xLAogICAgICAgIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3QobmFtZXMoZmlyc3RfdGltZXBvaW50JG9yaWcuaWRlbnRbZmlyc3RfdGltZXBvaW50JE9HX2NvbmRpdGlvbiA9PSAnY2lzJ10pKSwKICAgICAgICBjb2xzLmhpZ2hsaWdodCA9ICgncmVkJykpICsgZ2d0aXRsZSgnY2lzIGZpcnN0IGNlbGxzJykKCkZlYXR1cmVQbG90KGZpcnN0X3RpbWVwb2ludCwgZmVhdHVyZXMgPSAnRUdGUicsIHB0LnNpemUgPSAyKSArCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvcnMgPSByZXYoYnJld2VyLnBhbChuID0gMTEsIG5hbWUgPSAnUmRCdScpKSkKRmVhdHVyZVBsb3QoZmlyc3RfdGltZXBvaW50LCBmZWF0dXJlcyA9ICdOR0ZSJywgcHQuc2l6ZSA9IDIpICsKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG9ycyA9IHJldihicmV3ZXIucGFsKG4gPSAxMSwgbmFtZSA9ICdSZEJ1JykpKQoKCmRldi5vZmYoKQpgYGAKCiNNb3JlIHBsb3RzIG5vdCBpbiBQREYgYnV0IGp1c3QgZm9yIHF1aWNrIHZpc3VhbGl6YXRpb25zCmBgYHtyfQpEaW1QbG90KHNlY29uZF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgcHQuc2l6ZSA9IC4xLAogICAgICAgIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3QoY2VsbHNfcGVyX2NvbmRpdGlvbiRkYWJ0cmFtdG9kYWJ0cmFtX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGRhYnRyYW10b2Npc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRkYWJ0cmFtdG9jb2NsMl9jZWxscyksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSBjKCcjYTIyNDhlJywgJyM5ZDg1YmUnLCAnIzU2MWU1OScpKSArIGdndGl0bGUoJ2RhYnRyYW0gZmlyc3QgY2VsbHMnKQoKRGltUGxvdChzZWNvbmRfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KGNlbGxzX3Blcl9jb25kaXRpb24kZGFidHJhbXRvZGFidHJhbV9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRkYWJ0cmFtdG9jaXNfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kZGFidHJhbXRvY29jbDJfY2VsbHMpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gKCcjNjIzNTk0JykpICsgZ2d0aXRsZSgnZGFidHJhbSBmaXJzdCBjZWxscycpCgpEaW1QbG90KHNlY29uZF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgcHQuc2l6ZSA9IC4xLAogICAgICAgIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3QoY2VsbHNfcGVyX2NvbmRpdGlvbiRkYWJ0cmFtdG9kYWJ0cmFtX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvZGFidHJhbV9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjb2NsMnRvZGFidHJhbV9jZWxscyksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSBjKCcjMTA0MTNiJywgJyNhMjM2MjInLCAnIzU2MWU1OScpKSArIGdndGl0bGUoJ2RhYnRyYW0gc2Vjb25kIGNlbGxzJykKCkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChjZWxsc19wZXJfY29uZGl0aW9uJGRhYnRyYW10b2RhYnRyYW1fY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY2lzdG9kYWJ0cmFtX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNvY2wydG9kYWJ0cmFtX2NlbGxzKSwKICAgICAgICBjb2xzLmhpZ2hsaWdodCA9ICgnIzYyMzU5NCcpKSArIGdndGl0bGUoJ2RhYnRyYW0gc2Vjb25kIGNlbGxzJykKCmBgYAoKYGBge3J9CkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChjZWxsc19wZXJfY29uZGl0aW9uJGNvY2wydG9jb2NsMl9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjb2NsMnRvY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNvY2wydG9kYWJ0cmFtX2NlbGxzKSwKICAgICAgICBjb2xzLmhpZ2hsaWdodCA9IGMoJyMxMDQxM2InLCAnIzZkYzQ5YycsICcjNmFiZDQ1JykpICsgZ2d0aXRsZSgnY29jbDIgZmlyc3QgY2VsbHMnKQoKRGltUGxvdChzZWNvbmRfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KGNlbGxzX3Blcl9jb25kaXRpb24kY29jbDJ0b2NvY2wyX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNvY2wydG9jaXNfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY29jbDJ0b2RhYnRyYW1fY2VsbHMpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gKCcjMGY4MjQxJykpICsgZ2d0aXRsZSgnY29jbDIgZmlyc3QgY2VsbHMnKQoKRGltUGxvdChzZWNvbmRfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KGNlbGxzX3Blcl9jb25kaXRpb24kY29jbDJ0b2NvY2wyX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvY29jbDJfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kZGFidHJhbXRvY29jbDJfY2VsbHMpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gYygnI2EyMjQ4ZScsICcjZjQ5MTI5JywgJyM2YWJkNDUnKSkgKyBnZ3RpdGxlKCdjb2NsMiBzZWNvbmQgY2VsbHMnKQoKRGltUGxvdChzZWNvbmRfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KGNlbGxzX3Blcl9jb25kaXRpb24kY29jbDJ0b2NvY2wyX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvY29jbDJfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kZGFidHJhbXRvY29jbDJfY2VsbHMpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gKCcjMGY4MjQxJykpICsgZ2d0aXRsZSgnY29jbDIgc2Vjb25kIGNlbGxzJykKCmBgYAoKYGBge3J9CkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChjZWxsc19wZXJfY29uZGl0aW9uJGNpc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXN0b2Npc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXN0b2NvY2wyX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvZGFidHJhbV9jZWxscyksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSBjKCcjYTIzNjIyJywgJyNmNDkxMjknLCAnI2ZiZDA4YycpKSArIGdndGl0bGUoJ2NpcyBmaXJzdCBjZWxscycpCgpEaW1QbG90KHNlY29uZF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgcHQuc2l6ZSA9IC4xLAogICAgICAgIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3QoY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXNfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY2lzdG9jaXNfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY2lzdG9jb2NsMl9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXN0b2RhYnRyYW1fY2VsbHMpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gKCcjYzk2ZDI5JykpICsgZ2d0aXRsZSgnY2lzIGZpcnN0IGNlbGxzJykKCkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChjZWxsc19wZXJfY29uZGl0aW9uJGNpc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXN0b2Npc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjb2NsMnRvY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGRhYnRyYW10b2Npc19jZWxscyksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSBjKCcjOWQ4NWJlJywgJyM2ZGM0OWMnLCAnI2ZiZDA4YycpKSArIGdndGl0bGUoJ2NpcyBzZWNvbmQgY2VsbHMnKQoKRGltUGxvdChzZWNvbmRfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KGNlbGxzX3Blcl9jb25kaXRpb24kY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNvY2wydG9jaXNfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kZGFidHJhbXRvY2lzX2NlbGxzKSwKICAgICAgICBjb2xzLmhpZ2hsaWdodCA9ICgnI2M5NmQyOScpKSArIGdndGl0bGUoJ2NpcyBzZWNvbmQgY2VsbHMnKQoKYGBgCgojIFNhdmUgdGhlIG9iamVjdCB0byBsb2FkIGluIGZvciBkaXN0YW5jZSBtZXRyaWNzCmBgYHtyfQpzYXZlLmltYWdlKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy93b3Jrc3BhY2UuUkRhdGEnKQpgYGAKCiMgUnVuIGRpc3RhbmNlIG1ldHJpY3MKYGBge3J9CiMgRGVmaW5lIG1hbmhhdHRlbiBkaXN0YW5jZSBmdW5jdGlvbgptYW5oYXR0YW4uZGlzdGFuY2UgPC0gZnVuY3Rpb24oeCwgeSkgcmV0dXJuKHN1bShhYnMoeC15KSkpCgojIE1ha2UgbWV0YWRhdGEgb2JqZWN0cyBvZiB0aGUgZmlyc3QgYW5kIHNlY29uZCBjb25kaXRpb25zCnNlY29uZF90aW1lcG9pbnQkZmlyc3RfdHJlYXRtZW50IDwtIHNhcHBseShzdHJzcGxpdChzZWNvbmRfdGltZXBvaW50JE9HX2NvbmRpdGlvbiwgInRvIiksICJbWyIsIDEpCnNlY29uZF90aW1lcG9pbnQkc2Vjb25kX3RyZWF0bWVudCA8LSBzYXBwbHkoc3Ryc3BsaXQoc2Vjb25kX3RpbWVwb2ludCRPR19jb25kaXRpb24sICJ0byIpLCAiW1siLCAyKQoKIyBHZXQgaW5wdXQgZGF0YSBhbmQgc3ViZXN0CmlucHV0X2RhdGEgPC0gR2V0QXNzYXlEYXRhKHNlY29uZF90aW1lcG9pbnQsIGFzc2F5ID0gJ1JOQScsIHNsb3QgPSAnc2NhbGUuZGF0YScpCgojIE51bWJlciBvZiBjZWxscyBmb3Igc3Vic2V0dGluZwpudW1fY2VsbHMgPC0gMTAwMDAKCiMgTG9vayBhdCBncm91cGluZyBiYXNlZCBvbiBmaXJzdCBzYW1wbGUKSWRlbnRzKHNlY29uZF90aW1lcG9pbnQpIDwtIHNlY29uZF90aW1lcG9pbnQkZmlyc3RfdHJlYXRtZW50CkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCkKCmNvY2wyX2ZpcnN0X2NlbGxzIDwtICBzYW1wbGUobmFtZXMoc2Vjb25kX3RpbWVwb2ludCRmaXJzdF90cmVhdG1lbnQpW3NlY29uZF90aW1lcG9pbnQkZmlyc3RfdHJlYXRtZW50ID09ICdjb2NsMiddLCBudW1fY2VsbHMpCmNvY2wyX2ZpcnN0X3N1YnNldCA8LSBpbnB1dF9kYXRhWyxjb2NsMl9maXJzdF9jZWxsc10KY29jbDJfZmlyc3RfbWFuaGF0dGVuX2Rpc3RhbmNlIDwtIEN1c3RvbURpc3RhbmNlKGNvY2wyX2ZpcnN0X3N1YnNldCwgbWFuaGF0dGFuLmRpc3RhbmNlKQoKZGFidHJhbV9maXJzdF9jZWxscyA8LSAgc2FtcGxlKG5hbWVzKHNlY29uZF90aW1lcG9pbnQkZmlyc3RfdHJlYXRtZW50KVtzZWNvbmRfdGltZXBvaW50JGZpcnN0X3RyZWF0bWVudCA9PSAnZGFidHJhbSddLCBudW1fY2VsbHMpCmRhYnRyYW1fZmlyc3Rfc3Vic2V0IDwtIGlucHV0X2RhdGFbLGRhYnRyYW1fZmlyc3RfY2VsbHNdCmRhYnRyYW1fZmlyc3RfbWFuaGF0dGVuX2Rpc3RhbmNlIDwtIEN1c3RvbURpc3RhbmNlKGRhYnRyYW1fZmlyc3Rfc3Vic2V0LCBtYW5oYXR0YW4uZGlzdGFuY2UpCgpjaXNfZmlyc3RfY2VsbHMgPC0gIHNhbXBsZShuYW1lcyhzZWNvbmRfdGltZXBvaW50JGZpcnN0X3RyZWF0bWVudClbc2Vjb25kX3RpbWVwb2ludCRmaXJzdF90cmVhdG1lbnQgPT0gJ2NpcyddLCBudW1fY2VsbHMpCmNpc19maXJzdF9zdWJzZXQgPC0gaW5wdXRfZGF0YVssY2lzX2ZpcnN0X2NlbGxzXQpjaXNfZmlyc3RfbWFuaGF0dGVuX2Rpc3RhbmNlIDwtIEN1c3RvbURpc3RhbmNlKGNpc19maXJzdF9zdWJzZXQsIG1hbmhhdHRhbi5kaXN0YW5jZSkKCklkZW50cyhzZWNvbmRfdGltZXBvaW50KSA8LSBzZWNvbmRfdGltZXBvaW50JHNlY29uZF90cmVhdG1lbnQKRGltUGxvdChzZWNvbmRfdGltZXBvaW50KQoKY29jbDJfc2Vjb25kX2NlbGxzIDwtICBzYW1wbGUobmFtZXMoc2Vjb25kX3RpbWVwb2ludCRzZWNvbmRfdHJlYXRtZW50KVtzZWNvbmRfdGltZXBvaW50JHNlY29uZF90cmVhdG1lbnQgPT0gJ2NvY2wyJ10sIG51bV9jZWxscykKY29jbDJfc2Vjb25kX3N1YnNldCA8LSBpbnB1dF9kYXRhWyxjb2NsMl9zZWNvbmRfY2VsbHNdCmNvY2wyX3NlY29uZF9tYW5oYXR0ZW5fZGlzdGFuY2UgPC0gQ3VzdG9tRGlzdGFuY2UoY29jbDJfc2Vjb25kX3N1YnNldCwgbWFuaGF0dGFuLmRpc3RhbmNlKQoKZGFidHJhbV9zZWNvbmRfY2VsbHMgPC0gIHNhbXBsZShuYW1lcyhzZWNvbmRfdGltZXBvaW50JHNlY29uZF90cmVhdG1lbnQpW3NlY29uZF90aW1lcG9pbnQkc2Vjb25kX3RyZWF0bWVudCA9PSAnZGFidHJhbSddLCBudW1fY2VsbHMpCmRhYnRyYW1fc2Vjb25kX3N1YnNldCA8LSBpbnB1dF9kYXRhWyxkYWJ0cmFtX3NlY29uZF9jZWxsc10KZGFidHJhbV9zZWNvbmRfbWFuaGF0dGVuX2Rpc3RhbmNlIDwtIEN1c3RvbURpc3RhbmNlKGRhYnRyYW1fc2Vjb25kX3N1YnNldCwgbWFuaGF0dGFuLmRpc3RhbmNlKQoKY2lzX3NlY29uZF9jZWxscyA8LSAgc2FtcGxlKG5hbWVzKHNlY29uZF90aW1lcG9pbnQkc2Vjb25kX3RyZWF0bWVudClbc2Vjb25kX3RpbWVwb2ludCRzZWNvbmRfdHJlYXRtZW50ID09ICdjaXMnXSwgbnVtX2NlbGxzKQpjaXNfc2Vjb25kX3N1YnNldCA8LSBpbnB1dF9kYXRhWyxjaXNfc2Vjb25kX2NlbGxzXQpjaXNfc2Vjb25kX21hbmhhdHRlbl9kaXN0YW5jZSA8LSBDdXN0b21EaXN0YW5jZShjaXNfc2Vjb25kX3N1YnNldCwgbWFuaGF0dGFuLmRpc3RhbmNlKQoKcGxvdHRpbmdfZGYgPC0gZGF0YS5mcmFtZShHcm91cGluZyA9IGMocmVwKCdmaXJzdCcsMypsZW5ndGgoY2lzX2ZpcnN0X21hbmhhdHRlbl9kaXN0YW5jZSkpLHJlcCgnc2Vjb25kJywgMyoobGVuZ3RoKGNpc19zZWNvbmRfbWFuaGF0dGVuX2Rpc3RhbmNlKSkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBNYW5oYXR0ZW5fZGlzdCA8LSBjKGNvY2wyX2ZpcnN0X21hbmhhdHRlbl9kaXN0YW5jZSwgZGFidHJhbV9maXJzdF9tYW5oYXR0ZW5fZGlzdGFuY2UsIGNpc19maXJzdF9tYW5oYXR0ZW5fZGlzdGFuY2UsIGNvY2wyX3NlY29uZF9tYW5oYXR0ZW5fZGlzdGFuY2UsZGFidHJhbV9zZWNvbmRfbWFuaGF0dGVuX2Rpc3RhbmNlLCBjaXNfc2Vjb25kX21hbmhhdHRlbl9kaXN0YW5jZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgVHJlYXRtZW50ID0gYyhyZXAoJ0NvQ2wyIGZpcnN0JyxsZW5ndGgoY29jbDJfZmlyc3RfbWFuaGF0dGVuX2Rpc3RhbmNlKSkscmVwKCdEYWIvVHJhbSBmaXJzdCcsbGVuZ3RoKGRhYnRyYW1fZmlyc3RfbWFuaGF0dGVuX2Rpc3RhbmNlKSkscmVwKCdDaXNwbGF0aW4gZmlyc3QnLGxlbmd0aChjaXNfZmlyc3RfbWFuaGF0dGVuX2Rpc3RhbmNlKSkscmVwKCdDb0NsMiBzZWNvbmQnLGxlbmd0aChjb2NsMl9zZWNvbmRfbWFuaGF0dGVuX2Rpc3RhbmNlKSkscmVwKCdEYWIvVHJhbSBzZWNvbmQnLGxlbmd0aChkYWJ0cmFtX3NlY29uZF9tYW5oYXR0ZW5fZGlzdGFuY2UpKSxyZXAoJ0Npc3BsYXRpbiBzZWNvbmQnLGxlbmd0aChjaXNfc2Vjb25kX21hbmhhdHRlbl9kaXN0YW5jZSkpKSkKCmdncGxvdChwbG90dGluZ19kZiwgYWVzKHggPSBUcmVhdG1lbnQsIHkgPSBNYW5oYXR0ZW5fZGlzdCwgZmlsbCA9IEdyb3VwaW5nKSkgKyBnZW9tX3Zpb2xpbigpICsgZ2VvbV9ib3hwbG90KHdpZHRoID0gMC4xKQoKc2F2ZS5pbWFnZSgnMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvd29ya3NwYWNlX3YyLlJEYXRhJykKCmBgYAoKIyBUcnkgcGVhcnNvbiAtIGh0dHBzOi8vcHVibWVkLm5jYmkubmxtLm5paC5nb3YvMzAxMzcyNDcvCmBgYHtyfQoKI2xvYWQoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL3dvcmtzcGFjZV92Mi5SRGF0YScpCgpybShtYW5oYXR0ZW4uZGlzdGFuY2UsIGNvY2wyX2ZpcnN0X21hbmhhdHRlbl9kaXN0YW5jZSwgZGFidHJhbV9maXJzdF9tYW5oYXR0ZW5fZGlzdGFuY2UsIGNpc19maXJzdF9tYW5oYXR0ZW5fZGlzdGFuY2UsIGNvY2wyX3NlY29uZF9tYW5oYXR0ZW5fZGlzdGFuY2UsIGRhYnRyYW1fc2Vjb25kX21hbmhhdHRlbl9kaXN0YW5jZSwgY2lzX3NlY29uZF9tYW5oYXR0ZW5fZGlzdGFuY2UpCnJtKGNpcywgY2lzdG9jaXMsIGNpc3RvY29jbDIsIGNpc3RvZGFidHJhbSwgY29jbDIsIGNvY2wydG9jaXMsIGNvY2wydG9jb2NsMiwgY29jbDJ0b2RhYnRyYW0sIGRhYnRyYW0sIGRhYnRyYW10b2NpcywgZGFidHJhbXRvY29jbDIsIGRhYnRyYW10b2RhYnRyYW0pCmdjKCkKCiMgTWFrZSBtZXRhZGF0YSBvYmplY3RzIG9mIHRoZSBmaXJzdCBhbmQgc2Vjb25kIGNvbmRpdGlvbnMKc2Vjb25kX3RpbWVwb2ludCRmaXJzdF90cmVhdG1lbnQgPC0gc2FwcGx5KHN0cnNwbGl0KHNlY29uZF90aW1lcG9pbnQkT0dfY29uZGl0aW9uLCAidG8iKSwgIltbIiwgMSkKc2Vjb25kX3RpbWVwb2ludCRzZWNvbmRfdHJlYXRtZW50IDwtIHNhcHBseShzdHJzcGxpdChzZWNvbmRfdGltZXBvaW50JE9HX2NvbmRpdGlvbiwgInRvIiksICJbWyIsIDIpCgojIEdldCBpbnB1dCBkYXRhIGFuZCBzdWJlc3QKaW5wdXRfZGF0YSA8LSBHZXRBc3NheURhdGEoc2Vjb25kX3RpbWVwb2ludCwgYXNzYXkgPSAnUk5BJywgc2xvdCA9ICdzY2FsZS5kYXRhJykKCgojIExvb2sgYXQgZ3JvdXBpbmcgYmFzZWQgb24gZmlyc3Qgc2FtcGxlCklkZW50cyhzZWNvbmRfdGltZXBvaW50KSA8LSBzZWNvbmRfdGltZXBvaW50JGZpcnN0X3RyZWF0bWVudApEaW1QbG90KHNlY29uZF90aW1lcG9pbnQpCgpjb2NsMl9maXJzdF9jZWxscyA8LSAgbmFtZXMoc2Vjb25kX3RpbWVwb2ludCRmaXJzdF90cmVhdG1lbnQpW3NlY29uZF90aW1lcG9pbnQkZmlyc3RfdHJlYXRtZW50ID09ICdjb2NsMiddCmNvY2wyX2ZpcnN0X3N1YnNldCA8LSBpbnB1dF9kYXRhWyxjb2NsMl9maXJzdF9jZWxsc10KY29jbDJfZmlyc3RfcGVhcnNvbiA8LSBjb3IoY29jbDJfZmlyc3Rfc3Vic2V0KQpjb2NsMl9maXJzdF9wZWFyc29uX2ZpbHQgPC0gY29jbDJfZmlyc3RfcGVhcnNvbltsb3dlci50cmkoY29jbDJfZmlyc3RfcGVhcnNvbiwgZGlhZyA9IEZBTFNFKV0KCnNldC5zZWVkKDEpCmNvY2wyX2ZpcnN0X3N1YnNldF9yYW5kIDwtIGlucHV0X2RhdGFbLHNhbXBsZShjb2xuYW1lcyhpbnB1dF9kYXRhKSxsZW5ndGgoY29jbDJfZmlyc3RfY2VsbHMpKV0KY29jbDJfZmlyc3RfcGVhcnNvbl9yYW5kIDwtIGNvcihjb2NsMl9maXJzdF9zdWJzZXRfcmFuZCkKY29jbDJfZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQgPC0gY29jbDJfZmlyc3RfcGVhcnNvbl9yYW5kW2xvd2VyLnRyaShjb2NsMl9maXJzdF9wZWFyc29uX3JhbmQsIGRpYWcgPSBGQUxTRSldCgpkYWJ0cmFtX2ZpcnN0X2NlbGxzIDwtICBuYW1lcyhzZWNvbmRfdGltZXBvaW50JGZpcnN0X3RyZWF0bWVudClbc2Vjb25kX3RpbWVwb2ludCRmaXJzdF90cmVhdG1lbnQgPT0gJ2RhYnRyYW0nXQpkYWJ0cmFtX2ZpcnN0X3N1YnNldCA8LSBpbnB1dF9kYXRhWyxkYWJ0cmFtX2ZpcnN0X2NlbGxzXQpkYWJ0cmFtX2ZpcnN0X3BlYXJzb24gPC0gY29yKGRhYnRyYW1fZmlyc3Rfc3Vic2V0KQpkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdCA8LSBkYWJ0cmFtX2ZpcnN0X3BlYXJzb25bbG93ZXIudHJpKGRhYnRyYW1fZmlyc3RfcGVhcnNvbiwgZGlhZyA9IEZBTFNFKV0KCnNldC5zZWVkKDEpCmRhYnRyYW1fZmlyc3Rfc3Vic2V0X3JhbmQgPC0gaW5wdXRfZGF0YVssc2FtcGxlKGNvbG5hbWVzKGlucHV0X2RhdGEpLGxlbmd0aChkYWJ0cmFtX2ZpcnN0X2NlbGxzKSldCmRhYnRyYW1fZmlyc3RfcGVhcnNvbl9yYW5kIDwtIGNvcihkYWJ0cmFtX2ZpcnN0X3N1YnNldF9yYW5kKQpkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kIDwtIGRhYnRyYW1fZmlyc3RfcGVhcnNvbl9yYW5kW2xvd2VyLnRyaShkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fcmFuZCwgZGlhZyA9IEZBTFNFKV0KCmNpc19maXJzdF9jZWxscyA8LSAgbmFtZXMoc2Vjb25kX3RpbWVwb2ludCRmaXJzdF90cmVhdG1lbnQpW3NlY29uZF90aW1lcG9pbnQkZmlyc3RfdHJlYXRtZW50ID09ICdjaXMnXQpjaXNfZmlyc3Rfc3Vic2V0IDwtIGlucHV0X2RhdGFbLGNpc19maXJzdF9jZWxsc10KY2lzX2ZpcnN0X3BlYXJzb24gPC0gY29yKGNpc19maXJzdF9zdWJzZXQpCmNpc19maXJzdF9wZWFyc29uX2ZpbHQgPC0gY2lzX2ZpcnN0X3BlYXJzb25bbG93ZXIudHJpKGNpc19maXJzdF9wZWFyc29uLCBkaWFnID0gRkFMU0UpXQoKc2V0LnNlZWQoMSkKY2lzX2ZpcnN0X3N1YnNldF9yYW5kIDwtIGlucHV0X2RhdGFbLHNhbXBsZShjb2xuYW1lcyhpbnB1dF9kYXRhKSxsZW5ndGgoY2lzX2ZpcnN0X2NlbGxzKSldCmNpc19maXJzdF9wZWFyc29uX3JhbmQgPC0gY29yKGNpc19maXJzdF9zdWJzZXRfcmFuZCkKY2lzX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kIDwtIGNpc19maXJzdF9wZWFyc29uX3JhbmRbbG93ZXIudHJpKGNpc19maXJzdF9wZWFyc29uX3JhbmQsIGRpYWcgPSBGQUxTRSldCgpJZGVudHMoc2Vjb25kX3RpbWVwb2ludCkgPC0gc2Vjb25kX3RpbWVwb2ludCRzZWNvbmRfdHJlYXRtZW50CkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCkKCmNvY2wyX3NlY29uZF9jZWxscyA8LSAgbmFtZXMoc2Vjb25kX3RpbWVwb2ludCRzZWNvbmRfdHJlYXRtZW50KVtzZWNvbmRfdGltZXBvaW50JHNlY29uZF90cmVhdG1lbnQgPT0gJ2NvY2wyJ10KY29jbDJfc2Vjb25kX3N1YnNldCA8LSBpbnB1dF9kYXRhWyxjb2NsMl9zZWNvbmRfY2VsbHNdCmNvY2wyX3NlY29uZF9wZWFyc29uIDwtIGNvcihjb2NsMl9zZWNvbmRfc3Vic2V0KQpjb2NsMl9zZWNvbmRfcGVhcnNvbl9maWx0IDwtIGNvY2wyX3NlY29uZF9wZWFyc29uW2xvd2VyLnRyaShjb2NsMl9zZWNvbmRfcGVhcnNvbiwgZGlhZyA9IEZBTFNFKV0KCnNldC5zZWVkKDEpCmNvY2wyX3NlY29uZF9zdWJzZXRfcmFuZCA8LSBpbnB1dF9kYXRhWyxzYW1wbGUoY29sbmFtZXMoaW5wdXRfZGF0YSksbGVuZ3RoKGNvY2wyX3NlY29uZF9jZWxscykpXQpjb2NsMl9zZWNvbmRfcGVhcnNvbl9yYW5kIDwtIGNvcihjb2NsMl9zZWNvbmRfc3Vic2V0X3JhbmQpCmNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCA8LSBjb2NsMl9zZWNvbmRfcGVhcnNvbl9yYW5kW2xvd2VyLnRyaShjb2NsMl9zZWNvbmRfcGVhcnNvbl9yYW5kLCBkaWFnID0gRkFMU0UpXQoKZGFidHJhbV9zZWNvbmRfY2VsbHMgPC0gIG5hbWVzKHNlY29uZF90aW1lcG9pbnQkc2Vjb25kX3RyZWF0bWVudClbc2Vjb25kX3RpbWVwb2ludCRzZWNvbmRfdHJlYXRtZW50ID09ICdkYWJ0cmFtJ10KZGFidHJhbV9zZWNvbmRfc3Vic2V0IDwtIGlucHV0X2RhdGFbLGRhYnRyYW1fc2Vjb25kX2NlbGxzXQpkYWJ0cmFtX3NlY29uZF9wZWFyc29uIDwtIGNvcihkYWJ0cmFtX3NlY29uZF9zdWJzZXQpCmRhYnRyYW1fc2Vjb25kX3BlYXJzb25fZmlsdCA8LSBkYWJ0cmFtX3NlY29uZF9wZWFyc29uW2xvd2VyLnRyaShkYWJ0cmFtX3NlY29uZF9wZWFyc29uLCBkaWFnID0gRkFMU0UpXQoKc2V0LnNlZWQoMSkKZGFidHJhbV9zZWNvbmRfc3Vic2V0X3JhbmQgPC0gaW5wdXRfZGF0YVssc2FtcGxlKGNvbG5hbWVzKGlucHV0X2RhdGEpLGxlbmd0aChkYWJ0cmFtX3NlY29uZF9jZWxscykpXQpkYWJ0cmFtX3NlY29uZF9wZWFyc29uX3JhbmQgPC0gY29yKGRhYnRyYW1fc2Vjb25kX3N1YnNldF9yYW5kKQpkYWJ0cmFtX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCA8LSBkYWJ0cmFtX3NlY29uZF9wZWFyc29uX3JhbmRbbG93ZXIudHJpKGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fcmFuZCwgZGlhZyA9IEZBTFNFKV0KCmNpc19zZWNvbmRfY2VsbHMgPC0gIG5hbWVzKHNlY29uZF90aW1lcG9pbnQkc2Vjb25kX3RyZWF0bWVudClbc2Vjb25kX3RpbWVwb2ludCRzZWNvbmRfdHJlYXRtZW50ID09ICdjaXMnXQpjaXNfc2Vjb25kX3N1YnNldCA8LSBpbnB1dF9kYXRhWyxjaXNfc2Vjb25kX2NlbGxzXQpjaXNfc2Vjb25kX3BlYXJzb24gPC0gY29yKGNpc19zZWNvbmRfc3Vic2V0KQpjaXNfc2Vjb25kX3BlYXJzb25fZmlsdCA8LSBjaXNfc2Vjb25kX3BlYXJzb25bbG93ZXIudHJpKGNpc19zZWNvbmRfcGVhcnNvbiwgZGlhZyA9IEZBTFNFKV0KCnNldC5zZWVkKDEpCmNpc19zZWNvbmRfc3Vic2V0X3JhbmQgPC0gaW5wdXRfZGF0YVssc2FtcGxlKGNvbG5hbWVzKGlucHV0X2RhdGEpLGxlbmd0aChjaXNfc2Vjb25kX2NlbGxzKSldCmNpc19zZWNvbmRfcGVhcnNvbl9yYW5kIDwtIGNvcihjaXNfc2Vjb25kX3N1YnNldF9yYW5kKQpjaXNfc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kIDwtIGNpc19zZWNvbmRfcGVhcnNvbl9yYW5kW2xvd2VyLnRyaShjaXNfc2Vjb25kX3BlYXJzb25fcmFuZCwgZGlhZyA9IEZBTFNFKV0KCnNhdmUuaW1hZ2UoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL3dvcmtzcGFjZV92My5SRGF0YScpCgojIFNhdmUgQ29DbDIgb3V0cHV0cwpzYXZlKGNvY2wyX2ZpcnN0X3BlYXJzb24sIGNvY2wyX2ZpcnN0X3BlYXJzb25fcmFuZCwgY29jbDJfZmlyc3Rfc3Vic2V0LCBjb2NsMl9maXJzdF9zdWJzZXRfcmFuZCwgY29jbDJfZmlyc3RfcGVhcnNvbl9maWx0LCBjb2NsMl9maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCwgY29jbDJfc2Vjb25kX3BlYXJzb24sIGNvY2wyX3NlY29uZF9wZWFyc29uX3JhbmQsIGNvY2wyX3NlY29uZF9zdWJzZXQsIGNvY2wyX3NlY29uZF9zdWJzZXRfcmFuZCwgY29jbDJfc2Vjb25kX3BlYXJzb25fZmlsdCwgY29jbDJfc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kLCBmaWxlID0gJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2NvY2wyX3BlYXJzb25fcmVzdWx0cy5SRGF0YScpCnJtKGNvY2wyX2ZpcnN0X3BlYXJzb24sIGNvY2wyX2ZpcnN0X3BlYXJzb25fcmFuZCwgY29jbDJfZmlyc3Rfc3Vic2V0LCBjb2NsMl9maXJzdF9zdWJzZXRfcmFuZCwgY29jbDJfZmlyc3RfcGVhcnNvbl9maWx0LCBjb2NsMl9maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCwgY29jbDJfc2Vjb25kX3BlYXJzb24sIGNvY2wyX3NlY29uZF9wZWFyc29uX3JhbmQsIGNvY2wyX3NlY29uZF9zdWJzZXQsIGNvY2wyX3NlY29uZF9zdWJzZXRfcmFuZCwgY29jbDJfc2Vjb25kX3BlYXJzb25fZmlsdCwgY29jbDJfc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kKQoKIyBTYXZlIGRhYnRyYW0gb3V0cHV0cwpzYXZlKGRhYnRyYW1fZmlyc3RfcGVhcnNvbiwgZGFidHJhbV9maXJzdF9wZWFyc29uX3JhbmQsIGRhYnRyYW1fZmlyc3Rfc3Vic2V0LCBkYWJ0cmFtX2ZpcnN0X3N1YnNldF9yYW5kLCBkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdCwgZGFidHJhbV9maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCwgZGFidHJhbV9zZWNvbmRfcGVhcnNvbiwgZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9yYW5kLCBkYWJ0cmFtX3NlY29uZF9zdWJzZXQsIGRhYnRyYW1fc2Vjb25kX3N1YnNldF9yYW5kLCBkYWJ0cmFtX3NlY29uZF9wZWFyc29uX2ZpbHQsIGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kLCBmaWxlID0gJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2RhYnRyYW1fcGVhcnNvbl9yZXN1bHRzLlJEYXRhJykKcm0oZGFidHJhbV9maXJzdF9wZWFyc29uLCBkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fcmFuZCwgZGFidHJhbV9maXJzdF9zdWJzZXQsIGRhYnRyYW1fZmlyc3Rfc3Vic2V0X3JhbmQsIGRhYnRyYW1fZmlyc3RfcGVhcnNvbl9maWx0LCBkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kLCBkYWJ0cmFtX3NlY29uZF9wZWFyc29uLCBkYWJ0cmFtX3NlY29uZF9wZWFyc29uX3JhbmQsIGRhYnRyYW1fc2Vjb25kX3N1YnNldCwgZGFidHJhbV9zZWNvbmRfc3Vic2V0X3JhbmQsIGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fZmlsdCwgZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQpCgojIFNhdmUgY2lzIG91dHB1dHMKc2F2ZShjaXNfZmlyc3RfcGVhcnNvbiwgY2lzX2ZpcnN0X3BlYXJzb25fcmFuZCwgY2lzX2ZpcnN0X3N1YnNldCwgY2lzX2ZpcnN0X3N1YnNldF9yYW5kLCBjaXNfZmlyc3RfcGVhcnNvbl9maWx0LCBjaXNfZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQsIGNpc19zZWNvbmRfcGVhcnNvbiwgY2lzX3NlY29uZF9wZWFyc29uX3JhbmQsIGNpc19zZWNvbmRfc3Vic2V0LCBjaXNfc2Vjb25kX3N1YnNldF9yYW5kLCBjaXNfc2Vjb25kX3BlYXJzb25fZmlsdCwgY2lzX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCwgZmlsZSA9ICcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9jaXNfcGVhcnNvbl9yZXN1bHRzLlJEYXRhJykKcm0oY2lzX2ZpcnN0X3BlYXJzb24sIGNpc19maXJzdF9wZWFyc29uX3JhbmQsIGNpc19maXJzdF9zdWJzZXQsIGNpc19maXJzdF9zdWJzZXRfcmFuZCwgY2lzX2ZpcnN0X3BlYXJzb25fZmlsdCwgY2lzX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kLCBjaXNfc2Vjb25kX3BlYXJzb24sIGNpc19zZWNvbmRfcGVhcnNvbl9yYW5kLCBjaXNfc2Vjb25kX3N1YnNldCwgY2lzX3NlY29uZF9zdWJzZXRfcmFuZCwgY2lzX3NlY29uZF9wZWFyc29uX2ZpbHQsIGNpc19zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQpCmBgYAoKIyBTdGF0aXN0aWNhbCBhbmFseXNpcyBhbmQgcGxvdHRpbmcgb2YgcGVhcnNvbiBtZXRyaWNzIC0gQ29DbDIKYGBge3J9CmxvYWQoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2NvY2wyX3BlYXJzb25fcmVzdWx0cy5SRGF0YScpICMgTG9hZCBkYXRhCgpwZWFyc29uX3R0ZXN0X2NvY2wyX2ZpcnN0dnNyYW5kIDwtIHQudGVzdChjb2NsMl9maXJzdF9wZWFyc29uX2ZpbHQsIGNvY2wyX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kLCAgcGFpcmVkID0gRikKcGVhcnNvbl90dGVzdF9jb2NsMl9zZWNvbmR2c3JhbmQgPC0gdC50ZXN0KGNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHQsIGNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCwgIHBhaXJlZCA9IEYpCnBlYXJzb25fdHRlc3RfY29jbDJfc2Vjb25kdnNmaXJzdCA8LSB0LnRlc3QoY29jbDJfc2Vjb25kX3BlYXJzb25fZmlsdCwgY29jbDJfZmlyc3RfcGVhcnNvbl9maWx0LCAgcGFpcmVkID0gRikKcGVhcnNvbl90dGVzdF9jb2NsMl9yYW5kdnNyYW5kIDwtIHQudGVzdChjb2NsMl9zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQsIGNvY2wyX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kLCAgcGFpcmVkID0gRikKCnJtKGNvY2wyX2ZpcnN0X3BlYXJzb24sIGNvY2wyX2ZpcnN0X3BlYXJzb25fcmFuZCwgY29jbDJfZmlyc3Rfc3Vic2V0LCBjb2NsMl9maXJzdF9zdWJzZXRfcmFuZCwgY29jbDJfc2Vjb25kX3BlYXJzb24sIGNvY2wyX3NlY29uZF9wZWFyc29uX3JhbmQsIGNvY2wyX3NlY29uZF9zdWJzZXQsIGNvY2wyX3NlY29uZF9zdWJzZXRfcmFuZCkKCnBsb3R0aW5nX2RmX3BlYXJzb25fY29jbDIgPC0gZGF0YS5mcmFtZShHcm91cGluZyA9IGMocmVwKCdmaXJzdCcsbGVuZ3RoKGNvY2wyX2ZpcnN0X3BlYXJzb25fZmlsdCkpLCByZXAoJ3JhbmRvbScsbGVuZ3RoKGNvY2wyX2ZpcnN0X3BlYXJzb25fZmlsdCkpLCByZXAoJ3NlY29uZCcsIGxlbmd0aChjb2NsMl9zZWNvbmRfcGVhcnNvbl9maWx0KSksIHJlcCgncmFuZG9tJywgbGVuZ3RoKGNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHQpKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgUGVhcnNvbiA9IGMoY29jbDJfZmlyc3RfcGVhcnNvbl9maWx0LCBjb2NsMl9maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCwgY29jbDJfc2Vjb25kX3BlYXJzb25fZmlsdCwgY29jbDJfc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBUcmVhdG1lbnQgPSBjKHJlcCgnQ29DbDIgZmlyc3QnLGxlbmd0aChjb2NsMl9maXJzdF9wZWFyc29uX2ZpbHQpKSwgcmVwKCdDb0NsMiBmaXJzdCByYW5kJywgbGVuZ3RoKGNvY2wyX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kKSkscmVwKCdDb0NsMiBzZWNvbmQnLGxlbmd0aChjb2NsMl9zZWNvbmRfcGVhcnNvbl9maWx0KSkscmVwKCdDb0NsMiBzZWNvbmQgcmFuZCcsbGVuZ3RoKGNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCkpKSkKY29sbmFtZXMocGxvdHRpbmdfZGZfcGVhcnNvbl9jb2NsMikgPC0gYygnR3JvdXBpbmcnLCdQZWFyc29uJywnVHJlYXRtZW50JykKCnJtKGNvY2wyX2ZpcnN0X3BlYXJzb25fZmlsdCwgY29jbDJfZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQsIGNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHQsIGNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCkKZ2MoKQoKcGRmKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9jb2NsMl9wZWFyc29uX3Bsb3Rfc3Vic2FtcGxlZC5wZGYnKQpzZXQuc2VlZCgxKQpnZ3Bsb3QocGxvdHRpbmdfZGZfcGVhcnNvbl9jb2NsMltzYW1wbGUoMTpucm93KHBsb3R0aW5nX2RmX3BlYXJzb25fY29jbDIpLCAxMDAwMDAwMCksXSwgYWVzKHggPSBUcmVhdG1lbnQsIHkgPSBQZWFyc29uLCBmaWxsID0gR3JvdXBpbmcpKSArIGdlb21fdmlvbGluKCkgKyBnZW9tX2JveHBsb3Qod2lkdGggPSAwLjEsIG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjRkYwMDAwIiwgIiNEM0QzRDMiLCAiIzAwMDBGRiIpKQpkZXYub2ZmKCkKCiMgU2F2ZSBvdXRwdXRzCnNhdmUocGVhcnNvbl90dGVzdF9jb2NsMl9maXJzdHZzcmFuZCwgcGVhcnNvbl90dGVzdF9jb2NsMl9zZWNvbmR2c2ZpcnN0LCBwZWFyc29uX3R0ZXN0X2NvY2wyX3NlY29uZHZzcmFuZCwgcGVhcnNvbl90dGVzdF9jb2NsMl9yYW5kdnNyYW5kLCBmaWxlID0gJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2NvY2wyX3BlYXJzb25fdmFsdWVzLlJEYXRhJykKcm0ocGVhcnNvbl90dGVzdF9jb2NsMl9maXJzdHZzcmFuZCwgcGVhcnNvbl90dGVzdF9jb2NsMl9zZWNvbmR2c2ZpcnN0LCBwZWFyc29uX3R0ZXN0X2NvY2wyX3NlY29uZHZzcmFuZCwgcGVhcnNvbl90dGVzdF9jb2NsMl9yYW5kdnNyYW5kKQoKc2F2ZShwbG90dGluZ19kZl9wZWFyc29uX2NvY2wyLCBmaWxlID0gJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2NvY2wyX3BlYXJzb25fcGxvdHRpbmdfZGYuUkRhdGEnKQpybShwbG90dGluZ19kZl9wZWFyc29uX2NvY2wyKQpgYGAKCiMgU3RhdGlzdGljYWwgYW5hbHlzaXMgYW5kIHBsb3R0aW5nIG9mIHBlYXJzb24gbWV0cmljcyAtIGRhYnRyYW0KYGBge3J9CmxvYWQoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2RhYnRyYW1fcGVhcnNvbl9yZXN1bHRzLlJEYXRhJykgIyBMb2FkIGRhdGEKCnBlYXJzb25fdHRlc3RfZGFidHJhbV9maXJzdHZzcmFuZCA8LSB0LnRlc3QoZGFidHJhbV9maXJzdF9wZWFyc29uX2ZpbHQsIGRhYnRyYW1fZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQsICBwYWlyZWQgPSBGKQpwZWFyc29uX3R0ZXN0X2RhYnRyYW1fc2Vjb25kdnNyYW5kIDwtIHQudGVzdChkYWJ0cmFtX3NlY29uZF9wZWFyc29uX2ZpbHQsIGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kLCAgcGFpcmVkID0gRikKcGVhcnNvbl90dGVzdF9kYWJ0cmFtX3NlY29uZHZzZmlyc3QgPC0gdC50ZXN0KGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fZmlsdCwgZGFidHJhbV9maXJzdF9wZWFyc29uX2ZpbHQsICBwYWlyZWQgPSBGKQpwZWFyc29uX3R0ZXN0X2RhYnRyYW1fcmFuZHZzcmFuZCA8LSB0LnRlc3QoZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQsIGRhYnRyYW1fZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQsICBwYWlyZWQgPSBGKQoKcm0oZGFidHJhbV9maXJzdF9wZWFyc29uLCBkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fcmFuZCwgZGFidHJhbV9maXJzdF9zdWJzZXQsIGRhYnRyYW1fZmlyc3Rfc3Vic2V0X3JhbmQsIGRhYnRyYW1fc2Vjb25kX3BlYXJzb24sIGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fcmFuZCwgZGFidHJhbV9zZWNvbmRfc3Vic2V0LCBkYWJ0cmFtX3NlY29uZF9zdWJzZXRfcmFuZCkKCnBsb3R0aW5nX2RmX3BlYXJzb25fZGFidHJhbSA8LSBkYXRhLmZyYW1lKEdyb3VwaW5nID0gYyhyZXAoJ2ZpcnN0JyxsZW5ndGgoZGFidHJhbV9maXJzdF9wZWFyc29uX2ZpbHQpKSwgcmVwKCdyYW5kb20nLGxlbmd0aChkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdCkpLCByZXAoJ3NlY29uZCcsIGxlbmd0aChkYWJ0cmFtX3NlY29uZF9wZWFyc29uX2ZpbHQpKSwgcmVwKCdyYW5kb20nLCBsZW5ndGgoZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9maWx0KSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIFBlYXJzb24gPSBjKGRhYnRyYW1fZmlyc3RfcGVhcnNvbl9maWx0LCBkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kLCBkYWJ0cmFtX3NlY29uZF9wZWFyc29uX2ZpbHQsIGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBUcmVhdG1lbnQgPSBjKHJlcCgnZGFidHJhbSBmaXJzdCcsbGVuZ3RoKGRhYnRyYW1fZmlyc3RfcGVhcnNvbl9maWx0KSksIHJlcCgnZGFidHJhbSBmaXJzdCByYW5kJywgbGVuZ3RoKGRhYnRyYW1fZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQpKSxyZXAoJ2RhYnRyYW0gc2Vjb25kJyxsZW5ndGgoZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9maWx0KSkscmVwKCdkYWJ0cmFtIHNlY29uZCByYW5kJyxsZW5ndGgoZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQpKSkpCmNvbG5hbWVzKHBsb3R0aW5nX2RmX3BlYXJzb25fZGFidHJhbSkgPC0gYygnR3JvdXBpbmcnLCdQZWFyc29uJywnVHJlYXRtZW50JykKCnJtKGRhYnRyYW1fZmlyc3RfcGVhcnNvbl9maWx0LCBkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kLCBkYWJ0cmFtX3NlY29uZF9wZWFyc29uX2ZpbHQsIGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kKQpnYygpCgpwZGYoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2RhYnRyYW1fcGVhcnNvbl9wbG90X3N1YnNhbXBsZWQucGRmJykKc2V0LnNlZWQoMSkKZ2dwbG90KHBsb3R0aW5nX2RmX3BlYXJzb25fZGFidHJhbVtzYW1wbGUoMTpucm93KHBsb3R0aW5nX2RmX3BlYXJzb25fZGFidHJhbSksIDEwMDAwMDAwKSxdLCBhZXMoeCA9IFRyZWF0bWVudCwgeSA9IFBlYXJzb24sIGZpbGwgPSBHcm91cGluZykpICsgZ2VvbV92aW9saW4oKSArIGdlb21fYm94cGxvdCh3aWR0aCA9IDAuMSwgb3V0bGllci5zaGFwZSA9IE5BKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiNGRjAwMDAiLCAiI0QzRDNEMyIsICIjMDAwMEZGIikpCmRldi5vZmYoKQoKIyBTYXZlIG91dHB1dHMKc2F2ZShwZWFyc29uX3R0ZXN0X2RhYnRyYW1fZmlyc3R2c3JhbmQsIHBlYXJzb25fdHRlc3RfZGFidHJhbV9zZWNvbmR2c2ZpcnN0LCBwZWFyc29uX3R0ZXN0X2RhYnRyYW1fc2Vjb25kdnNyYW5kLHBlYXJzb25fdHRlc3RfZGFidHJhbV9yYW5kdnNyYW5kLCBmaWxlID0gJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2RhYnRyYW1fcGVhcnNvbl92YWx1ZXMuUkRhdGEnKQpybShwZWFyc29uX3R0ZXN0X2RhYnRyYW1fZmlyc3R2c3JhbmQsIHBlYXJzb25fdHRlc3RfZGFidHJhbV9zZWNvbmR2c2ZpcnN0LCBwZWFyc29uX3R0ZXN0X2RhYnRyYW1fc2Vjb25kdnNyYW5kLCBwZWFyc29uX3R0ZXN0X2RhYnRyYW1fcmFuZHZzcmFuZCkKCnNhdmUocGxvdHRpbmdfZGZfcGVhcnNvbl9kYWJ0cmFtLCBmaWxlID0gJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2RhYnRyYW1fcGVhcnNvbl9wbG90dGluZ19kZi5SRGF0YScpCnJtKHBsb3R0aW5nX2RmX3BlYXJzb25fZGFidHJhbSkKYGBgCgojIFN0YXRpc3RpY2FsIGFuYWx5c2lzIGFuZCBwbG90dGluZyBvZiBwZWFyc29uIG1ldHJpY3MgLSBjaXMKYGBge3J9CmxvYWQoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2Npc19wZWFyc29uX3Jlc3VsdHMuUkRhdGEnKSAjIExvYWQgZGF0YQoKcGVhcnNvbl90dGVzdF9jaXNfZmlyc3R2c3JhbmQgPC0gdC50ZXN0KGNpc19maXJzdF9wZWFyc29uX2ZpbHQsIGNpc19maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCwgIHBhaXJlZCA9IEYpCnBlYXJzb25fdHRlc3RfY2lzX3NlY29uZHZzcmFuZCA8LSB0LnRlc3QoY2lzX3NlY29uZF9wZWFyc29uX2ZpbHQsIGNpc19zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQsICBwYWlyZWQgPSBGKQpwZWFyc29uX3R0ZXN0X2Npc19zZWNvbmR2c2ZpcnN0IDwtIHQudGVzdChjaXNfc2Vjb25kX3BlYXJzb25fZmlsdCwgY2lzX2ZpcnN0X3BlYXJzb25fZmlsdCwgIHBhaXJlZCA9IEYpCnBlYXJzb25fdHRlc3RfY2lzX3JhbmR2c3JhbmQgPC0gdC50ZXN0KGNpc19zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQsIGNpc19maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCwgIHBhaXJlZCA9IEYpCgpybShjaXNfZmlyc3RfcGVhcnNvbiwgY2lzX2ZpcnN0X3BlYXJzb25fcmFuZCwgY2lzX2ZpcnN0X3N1YnNldCwgY2lzX2ZpcnN0X3N1YnNldF9yYW5kLCBjaXNfc2Vjb25kX3BlYXJzb24sIGNpc19zZWNvbmRfcGVhcnNvbl9yYW5kLCBjaXNfc2Vjb25kX3N1YnNldCwgY2lzX3NlY29uZF9zdWJzZXRfcmFuZCkKCnBsb3R0aW5nX2RmX3BlYXJzb25fY2lzIDwtIGRhdGEuZnJhbWUoR3JvdXBpbmcgPSBjKHJlcCgnZmlyc3QnLGxlbmd0aChjaXNfZmlyc3RfcGVhcnNvbl9maWx0KSksIHJlcCgncmFuZG9tJyxsZW5ndGgoY2lzX2ZpcnN0X3BlYXJzb25fZmlsdCkpLCByZXAoJ3NlY29uZCcsIGxlbmd0aChjaXNfc2Vjb25kX3BlYXJzb25fZmlsdCkpLCByZXAoJ3JhbmRvbScsIGxlbmd0aChjaXNfc2Vjb25kX3BlYXJzb25fZmlsdCkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBQZWFyc29uID0gYyhjaXNfZmlyc3RfcGVhcnNvbl9maWx0LCBjaXNfZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQsIGNpc19zZWNvbmRfcGVhcnNvbl9maWx0LCBjaXNfc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBUcmVhdG1lbnQgPSBjKHJlcCgnY2lzIGZpcnN0JyxsZW5ndGgoY2lzX2ZpcnN0X3BlYXJzb25fZmlsdCkpLCByZXAoJ2NpcyBmaXJzdCByYW5kJywgbGVuZ3RoKGNpc19maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCkpLHJlcCgnY2lzIHNlY29uZCcsbGVuZ3RoKGNpc19zZWNvbmRfcGVhcnNvbl9maWx0KSkscmVwKCdjaXMgc2Vjb25kIHJhbmQnLGxlbmd0aChjaXNfc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kKSkpKQpjb2xuYW1lcyhwbG90dGluZ19kZl9wZWFyc29uX2NpcykgPC0gYygnR3JvdXBpbmcnLCdQZWFyc29uJywnVHJlYXRtZW50JykKCnJtKGNpc19maXJzdF9wZWFyc29uX2ZpbHQsIGNpc19maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCwgY2lzX3NlY29uZF9wZWFyc29uX2ZpbHQsIGNpc19zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQpCmdjKCkKCnBkZignMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvY2lzX3BlYXJzb25fcGxvdF9zdWJzYW1wbGVkLnBkZicpCnNldC5zZWVkKDEpCmdncGxvdChwbG90dGluZ19kZl9wZWFyc29uX2Npc1tzYW1wbGUoMTpucm93KHBsb3R0aW5nX2RmX3BlYXJzb25fY2lzKSwgMTAwMDAwMDApLF0sIGFlcyh4ID0gVHJlYXRtZW50LCB5ID0gUGVhcnNvbiwgZmlsbCA9IEdyb3VwaW5nKSkgKyBnZW9tX3Zpb2xpbigpICsgZ2VvbV9ib3hwbG90KHdpZHRoID0gMC4xLCBvdXRsaWVyLnNoYXBlID0gTkEpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiI0ZGMDAwMCIsICIjRDNEM0QzIiwgIiMwMDAwRkYiKSkKZGV2Lm9mZigpCgojIFNhdmUgb3V0cHV0cwpzYXZlKHBlYXJzb25fdHRlc3RfY2lzX2ZpcnN0dnNyYW5kLCBwZWFyc29uX3R0ZXN0X2Npc19zZWNvbmR2c2ZpcnN0LCBwZWFyc29uX3R0ZXN0X2Npc19zZWNvbmR2c3JhbmQsIHBlYXJzb25fdHRlc3RfY2lzX3JhbmR2c3JhbmQsIGZpbGUgPSAnMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvY2lzX3BlYXJzb25fdmFsdWVzLlJEYXRhJykKcm0ocGVhcnNvbl90dGVzdF9jaXNfZmlyc3R2c3JhbmQsIHBlYXJzb25fdHRlc3RfY2lzX3NlY29uZHZzZmlyc3QsIHBlYXJzb25fdHRlc3RfY2lzX3NlY29uZHZzcmFuZCwgcGVhcnNvbl90dGVzdF9jaXNfcmFuZHZzcmFuZCkKCnNhdmUocGxvdHRpbmdfZGZfcGVhcnNvbl9jaXMsIGZpbGUgPSAnMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvY2lzX3BlYXJzb25fcGxvdHRpbmdfZGYuUkRhdGEnKQpybShwbG90dGluZ19kZl9wZWFyc29uX2NpcykKYGBgCgojIExvYWQgaW4gdGhlIHR0ZXN0IGRhdGEgYW5kIGNvbXBpbGUgaW50byBleGNlbCBzaGVldApgYGB7cn0KbG9hZCgnMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvY29jbDJfcGVhcnNvbl92YWx1ZXMuUkRhdGEnKQpsb2FkKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9kYWJ0cmFtX3BlYXJzb25fdmFsdWVzLlJEYXRhJykKbG9hZCgnMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvY2lzX3BlYXJzb25fdmFsdWVzLlJEYXRhJykKCmNvbXBhcmlzb25zIDwtICBjKCdkYWJ0cmFtX2ZpcnN0dnNyYW5kJywgJ2RhYnRyYW1fc2Vjb25kdnNyYW5kJywgJ2RhYnRyYW1fcmFuZHZzcmFuZCcsICdkYWJ0cmFtX3NlY29uZHZzZmlyc3QnLAogICAgICAgICAgICAgICAgICAnY29jbDJfZmlyc3R2c3JhbmQnLCAnY29jbDJfc2Vjb25kdnNyYW5kJywgJ2NvY2wyX3JhbmR2c3JhbmQnLCAnY29jbDJfc2Vjb25kdnNmaXJzdCcsCiAgICAgICAgICAgICAgICAgICdjaXNfZmlyc3R2c3JhbmQnLCAnY2lzX3NlY29uZHZzcmFuZCcsICdjaXNfcmFuZHZzcmFuZCcsICdjaXNfc2Vjb25kdnNmaXJzdCcpCgp0X3N0YXRpc3RpYyA8LSBjKHBlYXJzb25fdHRlc3RfZGFidHJhbV9maXJzdHZzcmFuZCRzdGF0aXN0aWMsIHBlYXJzb25fdHRlc3RfZGFidHJhbV9zZWNvbmR2c3JhbmQkc3RhdGlzdGljLCBwZWFyc29uX3R0ZXN0X2RhYnRyYW1fcmFuZHZzcmFuZCRzdGF0aXN0aWMsIHBlYXJzb25fdHRlc3RfZGFidHJhbV9zZWNvbmR2c2ZpcnN0JHN0YXRpc3RpYywKICAgICAgICAgICAgICAgICBwZWFyc29uX3R0ZXN0X2NvY2wyX2ZpcnN0dnNyYW5kJHN0YXRpc3RpYywgcGVhcnNvbl90dGVzdF9jb2NsMl9zZWNvbmR2c3JhbmQkc3RhdGlzdGljLHBlYXJzb25fdHRlc3RfY29jbDJfcmFuZHZzcmFuZCRzdGF0aXN0aWMsIHBlYXJzb25fdHRlc3RfY29jbDJfc2Vjb25kdnNmaXJzdCRzdGF0aXN0aWMsCiAgICAgICAgICAgICAgICAgcGVhcnNvbl90dGVzdF9jaXNfZmlyc3R2c3JhbmQkc3RhdGlzdGljLCBwZWFyc29uX3R0ZXN0X2Npc19zZWNvbmR2c3JhbmQkc3RhdGlzdGljLCBwZWFyc29uX3R0ZXN0X2Npc19yYW5kdnNyYW5kJHN0YXRpc3RpYywgcGVhcnNvbl90dGVzdF9jaXNfc2Vjb25kdnNmaXJzdCRzdGF0aXN0aWMpCgp0X3B2YWwgPC0gYyhwZWFyc29uX3R0ZXN0X2RhYnRyYW1fZmlyc3R2c3JhbmQkcC52YWx1ZSwgcGVhcnNvbl90dGVzdF9kYWJ0cmFtX3NlY29uZHZzcmFuZCRwLnZhbHVlLCBwZWFyc29uX3R0ZXN0X2RhYnRyYW1fcmFuZHZzcmFuZCRwLnZhbHVlLCBwZWFyc29uX3R0ZXN0X2RhYnRyYW1fc2Vjb25kdnNmaXJzdCRwLnZhbHVlLAogICAgICAgICAgICBwZWFyc29uX3R0ZXN0X2NvY2wyX2ZpcnN0dnNyYW5kJHAudmFsdWUsIHBlYXJzb25fdHRlc3RfY29jbDJfc2Vjb25kdnNyYW5kJHAudmFsdWUsIHBlYXJzb25fdHRlc3RfY29jbDJfcmFuZHZzcmFuZCRwLnZhbHVlLCBwZWFyc29uX3R0ZXN0X2NvY2wyX3NlY29uZHZzZmlyc3QkcC52YWx1ZSwKICAgICAgICAgICAgcGVhcnNvbl90dGVzdF9jaXNfZmlyc3R2c3JhbmQkcC52YWx1ZSwgcGVhcnNvbl90dGVzdF9jaXNfc2Vjb25kdnNyYW5kJHAudmFsdWUsIHBlYXJzb25fdHRlc3RfY2lzX3JhbmR2c3JhbmQkcC52YWx1ZSwgcGVhcnNvbl90dGVzdF9jaXNfc2Vjb25kdnNmaXJzdCRwLnZhbHVlKQoKdHRlc3RfZGYgPC0gZGF0YS5mcmFtZSgnQ29tcGFyaXNvbnMnID0gY29tcGFyaXNvbnMsICdUIHRlc3Qgc3RhdGlzdGljJyA9IHRfc3RhdGlzdGljLCAncCB2YWx1ZScgPSB0X3B2YWwpCgp3cml0ZS54bHN4KHR0ZXN0X2RmLCBmaWxlID0gJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL3BlYXJzb25fdHRlc3Rfc3RhdGlzdGljcy54bHN4JykKYGBgCgoKCg==